<?php

namespace App\V3\V3_2_6\Services;

use App\V3\Api\Services\StorageManageService;
use App\V3\V3_2_6\Models\LogOutPackageModel;
use App\V3\V3_2_6\Models\LogOutStorageModel;
use App\V3\V3_2_6\Models\LogPackageContentModel;
use App\V3\V3_2_6\Models\LogPackageModel;
use App\V3\V3_2_6\Models\MaterielProductContentModel;
use App\V3\V3_2_6\Models\MaterielsTypeModel;
use App\V3\V3_2_6\Models\MaterielTypeModel;
use App\V3\V3_2_6\Models\PackageContentModel;
use App\V3\V3_2_6\Models\PackageModel;
use App\V3\V3_2_6\Models\ProductOrderModel;
use App\V3\V3_2_6\Models\ProductSlaveContentStorageModel;
use App\V3\V3_2_6\Models\SellDriverModel;
use App\V3\V3_2_6\Models\SellGoodsBatchListModel;
use App\V3\V3_2_6\Models\SellGoodsDetailBatchModel;
use App\V3\V3_2_6\Models\SellGoodsListModel;
use App\V3\V3_2_6\Models\SellMaterielPrepareOutLogModel;
use App\V3\V3_2_6\Models\SellOutStoragePackageContentModel;
use App\V3\V3_2_6\Models\SellOutStoragePackageModel;
use App\V3\V3_2_6\Models\SellPackageBatchListModel;
use App\V3\V3_2_6\Models\SellPackageBatchModel;
use App\V3\V3_2_6\Models\SellPackageContentPrepareOutLogModel;
use App\V3\V3_2_6\Models\SellPackagePrepareOutLogModel;
use App\V3\V3_2_6\Models\SellPayRecordModel;
use App\V3\V3_2_6\Models\StorageBatchModel;
use App\V3\V3_2_6\Models\StorageManageModel;
use App\V3\V3_2_6\Models\SellGoodsDetailModel;
use App\V3\V3_2_6\Models\SellModel;
use App\V3\V3_2_6\Models\SellPackageContentModel;
use App\V3\V3_2_6\Models\SellPackageDetailModel;
use App\Helper\Utils\TimeUtil;
use App\V3\V3_2_6\Models\CheckModel;
use App\V3\V3_2_6\Models\SellGoodsDetail;
use App\V3\V3_2_6\Models\SellOtherChargesModel;
use App\V3\V3_2_6\Models\SellOutStorageModel;
use App\Services\MessageService;
use App\V3\V3_2_6\Models\StorageModel;
use Exception;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use App\V3\V3_2_6\Models\SerialNumberModel;
use App\V3\V3_2_6\Models\SellOutSerialNumbersModel;
use App\V3\V3_2_6\Models\SellPackageSerialNumberModel;
use App\V3\V3_2_6\Models\AdminModel;
use App\V3\V3_2_6\Models\AdminAddendumModel;
use App\V3\V3_2_6\Models\SalesReturnModel;
use App\V3\V3_2_6\Models\SupplierCustomerModel;

class SellService
{
    //新增-未使用批次号
    static public function add($mainInfo, $data)
    {
        //开启事务
        DB::beginTransaction();
        try{
            //创建销售主单信息
            $mainId = SellModel::insertGetId($mainInfo);
            $money = 0;//货款金额
            $materielInfo = [];
            $packageInfoArr = [];
            $productMaterielId = [];

            if(!empty($data['goods_info'])) {
                //商品详细添加
                $goodsInfo = json_decode($data['goods_info'],true);
                foreach ($goodsInfo as $key => $value){
                    if(empty($value['shelf_id']) || empty($value['location_id'])){
                       /*  $shelf_id = ShelfService::get_default($value['warehouse_id'])['id'];
                        $location_id = ShelfService::get_default($shelf_id,2)['id']; */

                        $sfData = ShelfService::get_default($value['warehouse_id']);

                        if(!empty($sfData)){
                            $shelf_id = $sfData['id'];
                            $lData = ShelfService::get_default($shelf_id,2);
                            $location_id = $lData['id'];
                        }else{
                            $shelf_id = 0;
                            $location_id = 0;
                            $value['shelf_id'] = 0;
                            $value['location_id'] = 0;
                        }
                    }else{
                        $shelf_id = $value['shelf_id'];
                        $location_id = $value['location_id'];
                    }

                    $materielTypeInfo = MaterielsTypeModel::where('id', $value['materiel_type_id'])->first();

                    if($materielTypeInfo['is_product_materiel']) {
                        $productMaterielId[] = [
                            'id' => $materielTypeInfo['id'],
                            'product_use_tag' => 1
                        ];

                        if($materielTypeInfo['selling_price'] == 0) {
                            $materielInfo[$key]['display_ratio'] = 0;
                            $materielInfo[$key]['calc_ratio'] = 0;
                        }
                        else {
                            if($materielTypeInfo['selling_price'] < $value['price']) {
                                if(!empty($materielTypeInfo['selling_price']) && !empty($value['price'])){
                                    $materielInfo[$key]['display_ratio'] = substr((($materielTypeInfo['selling_price'] - $value['price']) / $value['price']), 0, 4);
                                }else{
                                    $materielInfo[$key]['display_ratio'] = 0;
                                }
                            }
                            else {
                                if(!empty($materielTypeInfo['selling_price']) && !empty($value['price'])){
                                    $materielInfo[$key]['display_ratio'] = substr(($value['price'] / $materielTypeInfo['selling_price']), 0, 4);
                                }else{
                                    $materielInfo[$key]['display_ratio'] = 0;
                                }

                            }

                            if(!empty($materielTypeInfo['selling_price']) && !empty($value['price'])){
                                $materielInfo[$key]['calc_ratio'] = sprintf('%.2f', ($value['price'] / $materielTypeInfo['selling_price']));
                            }else{
                                $materielInfo[$key]['calc_ratio'] = 0;
                                $materielInfo[$key]['display_ratio'] = 0;
                            }
                        }
                    }
                    else {
                        $materielInfo[$key]['display_ratio'] = 0;
                        $materielInfo[$key]['calc_ratio'] = 0;
                    }

                    $materielInfo[$key]['is_product_materiel'] = $materielTypeInfo['is_product_materiel'];
                    $materielInfo[$key]['materiel_type_id'] = $value['materiel_type_id'];
                    $materielInfo[$key]['name'] = $value['name'];
                    $materielInfo[$key]['type_name'] = $value['type_name'];
                    $materielInfo[$key]['price'] = $value['price'];
                    $materielInfo[$key]['num'] = $value['num'];
                    $materielInfo[$key]['image'] = $value['image'];
                    $materielInfo[$key]['warehouse'] = $value['warehouse'];
                    $materielInfo[$key]['warehouse_id'] = $value['warehouse_id'];
                    $materielInfo[$key]['main_id'] = $mainInfo['main_id'];
                    $materielInfo[$key]['sell_date'] = strtotime(date('Y-m-d',strtotime($data['sell_date'])));
                    $materielInfo[$key]['sell_id'] = $mainId;
                    $materielInfo[$key]['created_at'] = time();
                    $money+=($value['price']*$value['num']);

                    $materielInfo[$key]['shelf_id'] = empty($shelf_id)?0:$shelf_id;
                    $materielInfo[$key]['location_id'] = empty($location_id)?0:$location_id;

                }

                SellGoodsDetailModel::insert($materielInfo);
            }

            if(!empty($data['package_info'])) {
                $packageInfo = json_decode($data['package_info'], true);

                foreach($packageInfo as $k => $val) {
                    if(!is_int($val['num'] * 1)) {
                        throw new Exception('套餐数量只能为整数');
                    }
                    $money+=($val['price']*$val['num']);
                    $packageInfoArr[$k]['package_id'] = $val['package_id'];
                    $packageInfoArr[$k]['price'] = $val['price'];
                    $packageInfoArr[$k]['total_cost'] = self::getPackageCost($val['package_id']);
                    $packageInfoArr[$k]['sell_id'] = $mainId;
                    $packageInfoArr[$k]['num'] = $val['num'];
//                    $packageInfoArr[$k]['remark'] = $val['remark'];
                    $packageInfoArr[$k]['user_id'] = $mainInfo['user_id'];
                    $packageInfoArr[$k]['main_id'] = $mainInfo['main_id'];
                    $packageInfoArr[$k]['package_content'] = $val['package_content'];
                    $packageInfoArr[$k]['sell_date'] = strtotime(date('Y-m-d',strtotime($data['sell_date'])));
                    $packageInfoArr[$k]['created_at'] = time();
                }

                foreach($packageInfoArr as $vv) {
                    $batchNo = $data['batch_title'].date('YmdHis', time()) .mt_rand(10000, 99999).'a';
                    do {
                        $batchNo = $data['batch_title'].date('YmdHis', time()) .mt_rand(10000, 99999).'a';
                    }
                    while(!empty(SellPackageDetailModel::where('package_no', $batchNo)->first()));
                    $packageId = SellPackageDetailModel::insertGetId([
                        'package_id' => $vv['package_id'],
                        'package_no' => $batchNo,
                        'price' => $vv['price'],
                        'total_cost' => $vv['total_cost'],
                        'sell_id' => $vv['sell_id'],
                        'num' => $vv['num'],
//                        'remark' => $vv['remark'],
                        'user_id' => $mainInfo['user_id'],
                        'main_id' => $mainInfo['main_id'],
                        'sell_date' => $vv['sell_date'],
                        'created_at' => $vv['created_at'],
                    ]);

                    foreach($vv['package_content'] as $vvv) {

                        if(empty($vvv['shelf_id']) || empty($vvv['location_id'])){

                            $sfData = ShelfService::get_default($vvv['storage_id']);
                            if(!empty($sfData)){
                                $shelf_id = $sfData['id'];
                                $lData = ShelfService::get_default($shelf_id,2);
                                $location_id = $lData['id'];
                                $vvv['shelf_id'] = $shelf_id;
                                $vvv['location_id'] = $location_id;
                            }
                        }

                        SellPackageContentModel::insert([
                            'materiel_class_id' => $vvv['materiel_class_id'],
                            'materiel_type_id' => $vvv['materiel_type_id'],
                            'storage_id' => $vvv['storage_id'],
                            'package_content_id' => $vvv['id'],
                            'storage_manage_id' => $vvv['storage_manage_id'],
                            'package_id' => $vv['package_id'],
                            'package_detail_id' => $packageId,
                            'sell_id' => $mainId,
                            'total_num' => $vvv['num'] * $vv['num'],
                            'rest_num' => $vvv['num'] * $vv['num'],
                            'num' => $vvv['num'],
                            'user_id' => $mainInfo['user_id'],
                            'main_id' => $mainInfo['main_id'],
                            'created_at' => time(),

                            'shelf_id' => empty($vvv['shelf_id'])?0:$vvv['shelf_id'],
                            'location_id' =>empty($vvv['location_id'])?0:$vvv['location_id'],
                        ]);
                    }
                }
            }

            //非改价计算价格
            if(!$data['is_zero_suppression'] && $money){
                $finalMoney = 0;
                if(isset($data['discount']) && $data['discount']){//折扣
                    $finalMoney+= ($data['discount']*$money/100);
                }else{
                    $finalMoney = $money;
                }
                if(isset($data['tax_rate']) && $data['tax_rate']){//加税点
                    $finalMoney+= ($data['tax_rate']*$finalMoney/100);
                }

                SellModel::where('id',$mainId)->update(['final_money'=>$finalMoney,'money'=>$money]);
            }else{
                SellModel::where('id',$mainId)->update(['money'=>$money]);
            }

            //审核列表
            CheckModel::insert([
                'type'=>2,
                'all_id'=>$mainId,
                'main_id'=>$mainInfo['main_id'],
                'user_id'=>$mainInfo['user_id'],
                'order_no'=>$mainInfo['order_no'],
                'created_at'=>time(),
            ]);

            if(!empty($productMaterielId)) {
                batch()->update(new MaterielTypeModel, $productMaterielId, 'id');
            }

            DB::commit();//提交事务
            return ['code' => 0, 'msg' => 'success', 'data' => $mainId];
        }catch (Exception $e){

            DB::rollBack();//事务回滚
            Log::debug('添加销售单异常:'.var_export($e->getMessage(), true));
            //异常响应
            return ['code' => 1, 'msg' => $e->getMessage(), 'data' => ''];
        }
    }

    //新增-使用批次号
    static public function addWithBatch($mainInfo, $data)
    {
        //开启事务
        DB::beginTransaction();
        try{
            //创建销售主单信息
            $mainId = SellModel::insertGetId($mainInfo);
            $money = 0;//货款金额
            $materielInfo = [];
            $packageInfoArr = [];

            if(!empty($data['goods_info'])) {
                //商品详细添加
                $goodsInfo = json_decode($data['goods_info'],true);

                $batchInfo = [];
                foreach ($goodsInfo as $key => $value){
                    $arr = [
                        'materiel_type_id' => $value['materiel_type_id'],
                        'name' => $value['name'],
                        'type_name' => $value['type_name'],
                        'price' => $value['price'],
                        'num' => $value['num'],
                        'image' => $value['image'],
                        'warehouse' => $value['warehouse'],
                        'warehouse_id' => $value['warehouse_id'],
                        'main_id' => $mainInfo['main_id'],
                        'sell_date' => strtotime(date('Y-m-d',strtotime($data['sell_date']))),
                        'sell_id' => $mainId,
                        'created_at' => time(),
                    ];

                    $sellGoodsDetailId = SellGoodsDetailModel::insertGetId($arr);

                    $batchTotalNum = 0;
                    foreach($value['batch_info'] as $val) {
                        $batchTotalNum += $val['num'];

                        $batchInfo[] = [
                            'storage_batch_id' => $val['batch_id'],
                            'storage_manage_id' => $val['storage_manage_id'],
                            'sell_goods_detail_id' => $sellGoodsDetailId,
                            'num' => $val['num'],
                            'sell_id' => $mainId,
                            'main_id' => $mainInfo['main_id'],
                            'rest_num' => $val['num'],
                            'created_at' => time()
                        ];
                    }

                    if($value['num'] < $batchTotalNum) {
                        return ['code' => 1, 'msg' => '商品:'.$value['name'].'-'.$value['type_name'].'批次总数量超出商品销售总数', 'data' => ''];
                    }

                    if($value['num'] > $batchTotalNum) {
                        return ['code' => 1, 'msg' => '商品:'.$value['name'].'-'.$value['type_name'].'批次总数量小于商品销售总数', 'data' => ''];
                    }
                }

                SellGoodsDetailBatchModel::insert($batchInfo);
            }

            if(!empty($data['package_info'])) {
                $packageInfo = json_decode($data['package_info'], true);

                foreach($packageInfo as $k => $val) {
                    $money+=($val['price']*$val['num']);
                    $packageInfoArr[$k]['package_id'] = $val['package_id'];
                    $packageInfoArr[$k]['price'] = $val['price'];
                    $packageInfoArr[$k]['total_cost'] = self::getPackageCost($val['package_id']);
                    $packageInfoArr[$k]['sell_id'] = $mainId;
                    $packageInfoArr[$k]['num'] = $val['num'];
                    $packageInfoArr[$k]['user_id'] = $mainInfo['user_id'];
                    $packageInfoArr[$k]['main_id'] = $mainInfo['main_id'];
                    $packageInfoArr[$k]['package_content'] = $val['package_content'];
                    $packageInfoArr[$k]['sell_date'] = strtotime(date('Y-m-d',strtotime($data['sell_date'])));
                    $packageInfoArr[$k]['created_at'] = time();
                }

                $arr = [];
                foreach($packageInfoArr as $vv) {
                    $batchNo = $data['batch_title'].date('YmdHis', time()) .mt_rand(10000, 99999).'a';

                    do {
                        $batchNo = $data['batch_title'].date('YmdHis', time()) .mt_rand(10000, 99999).'a';
                    }
                    while(!empty(SellPackageDetailModel::where('package_no', $batchNo)->first()));
                    $packageId = SellPackageDetailModel::insertGetId([
                        'package_id' => $vv['package_id'],
                        'package_no' => $batchNo,
                        'price' => $vv['price'],
                        'total_cost' => $vv['total_cost'],
                        'sell_id' => $vv['sell_id'],
                        'num' => $vv['num'],
//                        'remark' => $vv['remark'],
                        'user_id' => $mainInfo['user_id'],
                        'main_id' => $mainInfo['main_id'],
                        'sell_date' => $vv['sell_date'],
                        'created_at' => $vv['created_at'],
                    ]);

                    foreach($vv['package_content'] as $vvv) {
                        $packageContentId = SellPackageContentModel::insertGetId([
                            'materiel_class_id' => $vvv['materiel_class_id'],
                            'type_id' => $vvv['type_id'],
                            'storage_id' => $vvv['storage_id'],
                            'package_content_id' => $vvv['id'],
                            'storage_manage_id' => $vvv['storage_manage_id'],
                            'package_id' => $vv['package_id'],
                            'package_detail_id' => $packageId,
                            'sell_id' => $mainId,
                            'total_num' => $vvv['num'] * $vv['num'],
                            'num' => $vvv['num'],
                            'user_id' => $mainInfo['user_id'],
                            'main_id' => $mainInfo['main_id'],
                            'created_at' => time()
                        ]);


                        $batchTotalNum = 0;
                        foreach($vvv['batch_info'] as $v) {
                            $batchTotalNum += $v['num'];

                            $arr[] = [
                                'sell_package_content_id' => $packageContentId,
                                'storage_manage_id' => $v['storage_manage_id'],
                                'storage_batch_id' => $v['batch_id'],
                                'num' => $v['num'],
                                'sell_id' => $mainId,
                                'main_id' => $mainInfo['main_id'],
                                'rest_num' => $v['num'],
                                'created_at' => time()
                            ];
                        }

                        if($batchTotalNum > ($vvv['num'] * $vv['num'])) {
                            return ['code' => 1, 'msg' => '单个套餐内商品数小于对应的商品批次总数', 'data' => ''];
                        }

                        if($batchTotalNum < ($vvv['num'] * $vv['num'])) {
                            return ['code' => 1, 'msg' => '单个套餐内商品数超出对应的商品批次总数', 'data' => ''];
                        }
                    }
                }

                SellPackageBatchModel::insert($arr);
            }

            //非改价计算价格
            if(!$data['is_zero_suppression'] && $money){
                $finalMoney = 0;
                if(isset($data['discount']) && $data['discount']){//折扣
                    $finalMoney+= ($data['discount']*$money/100);
                }else{
                    $finalMoney = $money;
                }
                if(isset($data['tax_rate']) && $data['tax_rate']){//加税点
                    $finalMoney+= ($data['tax_rate']*$finalMoney/100);
                }

                SellModel::where('id',$mainId)->update(['final_money'=>$finalMoney,'money'=>$money]);
            }else{
                SellModel::where('id',$mainId)->update(['money'=>$money]);
            }

            //审核列表
            CheckModel::insert([
                'type'=>2,
                'all_id'=>$mainId,
                'main_id'=>$mainInfo['main_id'],
                'user_id'=>$mainInfo['user_id'],
                'order_no'=>$mainInfo['order_no'],
                'created_at'=>time(),
            ]);

            DB::commit();//提交事务
            return ['code' => 0, 'msg' => 'success', 'data' => $mainId];
        }catch (Exception $e){
            DB::rollBack();//事务回滚
            Log::debug('添加销售单异常:'.var_export($e->getMessage(), true));
            //异常响应
            return ['code' => 1, 'msg' => $e->getMessage(), 'data' => ''];
        }
    }

    static public function edit($mainInfo, $data)
    {
        DB::beginTransaction();
        try {
            $oldSellGoodsInfo = SellGoodsDetailModel::select('id')
                ->where('sell_id', $mainInfo['id'])->get()->toArray();
            $sellGoodsId = [];
            foreach($oldSellGoodsInfo as $sg) {
                $sellGoodsId[] = $sg['id'];
            }

            $oldSellPackageInfo = SellPackageDetailModel::select('id')
                ->where('sell_id', $mainInfo['id'])->get()->toArray();
            $sellPackageId = [];
            foreach($oldSellPackageInfo as $sp) {
                $sellPackageId[] = $sp['id'];
            }

            $oldSellPackageContent = SellPackageContentModel::select('id')
                ->where('sell_id', $mainInfo['id'])->get()->toArray();
            $sellPackageContentId = [];
            foreach($oldSellPackageContent as $spc) {
                $sellPackageContentId[] = $spc['id'];
            }

            $money = 0;//货款金额
            $materielInfo = [];
            $packageInfoArr = [];
            $productMaterielId = [];

            if(!empty($data['goods_info'])) {
                //商品详细添加
                $goodsInfo = json_decode($data['goods_info'],true);
                foreach ($goodsInfo as $key => $value){
                    $materielTypeInfo = MaterielsTypeModel::where('id', $value['materiel_type_id'])->first();

                    if($materielTypeInfo['is_product_materiel']) {
                        $productMaterielId[] = [
                            'id' => $materielTypeInfo['id'],
                            'product_use_tag' => 1
                        ];

                        if($materielTypeInfo['selling_price'] < $value['price']) {
                            $materielInfo[$key]['display_ratio'] = 0;
                            if(!empty($materielTypeInfo['selling_price']) && !empty($value['price'])){
                                $materielInfo[$key]['display_ratio'] = substr((($materielTypeInfo['selling_price'] - $value['price']) / $value['price']), 0, 4);
                            }
                        }else {
                            $materielInfo[$key]['display_ratio'] = 0;
                            if(!empty($materielTypeInfo['selling_price']) && !empty($value['price'])){
                                $materielInfo[$key]['display_ratio'] = substr(($value['price'] / $materielTypeInfo['selling_price']), 0, 4);
                            }
                        }
                        $materielInfo[$key]['calc_ratio'] = 0;
                        if(!empty($materielTypeInfo['selling_price']) && !empty($value['price'])){
                            $materielInfo[$key]['calc_ratio'] = sprintf('%.2f', ($value['price'] / $materielTypeInfo['selling_price']));
                        }
                    }
                    else {
                        $materielInfo[$key]['display_ratio'] = 0;
                        $materielInfo[$key]['calc_ratio'] = 0;
                    }

                    $materielInfo[$key]['is_product_materiel'] = $materielTypeInfo['is_product_materiel'];
                    $materielInfo[$key]['materiel_type_id'] = $value['materiel_type_id'];
                    $materielInfo[$key]['name'] = $value['name'];
                    $materielInfo[$key]['type_name'] = $value['type_name'];
                    $materielInfo[$key]['price'] = $value['price'];
                    $materielInfo[$key]['piece'] = empty($value['piece'])?0:$value['piece'];
                    $materielInfo[$key]['num'] = $value['num'];
//                    $materielInfo[$key]['remark'] = isset($value['remark'])?:$value['remark'];
                    $materielInfo[$key]['image'] = $value['image'];
                    $materielInfo[$key]['warehouse'] = $value['warehouse'];
                    $materielInfo[$key]['warehouse_id'] = $value['warehouse_id'];
                    $materielInfo[$key]['main_id'] = $mainInfo['main_id'];
                    $materielInfo[$key]['sell_date'] = strtotime(date('Y-m-d',strtotime($data['sell_date'])));
                    $materielInfo[$key]['sell_id'] = $mainInfo['id'];
                    $materielInfo[$key]['created_at'] = time();
                    $money+=($value['price']*$value['num']);

                    $materielInfo[$key]['shelf_id'] = empty($value['shelf_id'])?0:$value['shelf_id'];
                    $materielInfo[$key]['location_id'] = empty($value['location_id'])?0:$value['location_id'];

                }

                SellGoodsDetailModel::insert($materielInfo);
            }

            if(!empty($data['package_info'])) {
                //商品详细添加
                $packageInfo = json_decode($data['package_info'],true);
                foreach ($packageInfo as $k => $val){
                    if(!is_integer($val['num'] * 1)) {
                        throw new Exception('套餐数量只能为整数');
                    }
                    $money+=($val['price']*$val['num']);
                    $packageInfoArr[$k]['package_id'] = $val['package_id'];
                    $packageInfoArr[$k]['total_cost'] = self::getPackageCost($val['package_id']);
                    $packageInfoArr[$k]['price'] = $val['price'];
                    $packageInfoArr[$k]['sell_id'] = $mainInfo['id'];
//                    $packageInfoArr[$k]['remark'] = $val['remark'];
                    $packageInfoArr[$k]['num'] = $val['num'];
                    $packageInfoArr[$k]['piece'] = empty($val['piece'])?0:$val['piece'];
                    $packageInfoArr[$k]['user_id'] = $mainInfo['user_id'];
                    $packageInfoArr[$k]['main_id'] = $mainInfo['main_id'];
                    $packageInfoArr[$k]['package_content'] = $val['package_content'];
                    $packageInfoArr[$k]['sell_date'] = strtotime(date('Y-m-d',strtotime($data['sell_date'])));
                    $packageInfoArr[$k]['created_at'] = time();
                }

                foreach($packageInfoArr as $vv) {
                    $batchNo = $data['batch_title'].date('YmdHis', time()) .mt_rand(10000, 99999).'a';
                    $packageId = SellPackageDetailModel::insertGetId([
                        'package_id' => $vv['package_id'],
                        'package_no' => $batchNo,
                        'price' => $vv['price'],
                        'total_cost' => $vv['total_cost'],
                        'sell_id' => $vv['sell_id'],
                        'num' => $vv['num'],
                        'piece' => $vv['piece'],
//                        'remark' => $vv['remark'],
                        'user_id' => $mainInfo['user_id'],
                        'main_id' => $mainInfo['main_id'],
                        'sell_date' => $vv['sell_date'],
                        'created_at' => $vv['created_at'],
                    ]);

                    foreach($vv['package_content'] as $vvv) {
                        SellPackageContentModel::insert([
                            'materiel_class_id' => $vvv['materiel_class_id'],
                            'materiel_type_id' => $vvv['materiel_type_id'],
                            'storage_id' => $vvv['storage_id'],
                            'package_content_id' => $vvv['id'],
                            'package_id' => $vv['package_id'],
                            'storage_manage_id' => $vvv['storage_manage_id'],
                            'package_detail_id' => $packageId,
                            'sell_id' => $mainInfo['id'],
                            'num' => $vvv['num'],
                            'total_num' => $vvv['num'] * $vv['num'],
                            'rest_num' => $vvv['num'] * $vv['num'],
                            'user_id' => $mainInfo['user_id'],
                            'main_id' => $mainInfo['main_id'],
                            'created_at' => time(),

                            'shelf_id' => empty($vvv['shelf_id'])?0:$vvv['shelf_id'],
                            'location_id' => empty($vvv['location_id'])?0:$vvv['location_id'],
                        ]);
                    }
                }
            }

            //非改价计算价格
            if(!$data['is_zero_suppression'] && $money){
                $finalMoney = 0;
                if(isset($data['discount']) && $data['discount']){//折扣
                    $finalMoney+= ($data['discount']*$money/100);
                }else{
                    $finalMoney = $money;
                }

                if(isset($data['tax_rate']) && $data['tax_rate']){//加税点
                    $finalMoney+= ($data['tax_rate']*$finalMoney/100);
                }

                $mainInfo['final_money'] = $finalMoney;
                $mainInfo['money'] = $money;
            }else{
                $mainInfo['money'] = $money;
            }
            unset($mainInfo['goods_info']);
            unset($mainInfo['package_info']);

            //实收全部结清更新支付状态为全部
//            if(isset($mainInfo['real_money']) && (string)$mainInfo['real_money']==(string)$finalMoney){
//                $mainInfo['pay_status'] =2;
//            }
            //司机更新添加
            if(isset($mainInfo['driver']) && !empty($mainInfo['driver'])){
                $driver = SellDriverModel::where('sell_id',$data['id'])->first();
                if($driver){
                    SellDriverModel::where('sell_id',$data['id'])->update(json_decode($mainInfo['driver'],true));
                }else{
                    $newDriver = json_decode($mainInfo['driver'],true);
                    $newDriver['sell_id'] = $data['id'];
                    $newDriver['main_id'] = $mainInfo['main_id'];
                    SellDriverModel::insert($newDriver);
                }
                unset($mainInfo['driver']);
            }

            //删除旧销售单信息
            SellGoodsDetailModel::whereIn('id', $sellGoodsId)->delete();
            SellPackageDetailModel::whereIn('id', $sellPackageId)->delete();
            SellPackageContentModel::whereIn('id', $sellPackageContentId)->delete();

            if(!empty($productMaterielId)) {
                batch()->update(new MaterielTypeModel, $productMaterielId, 'id');
            }
            //更新销售单
            SellModel::where('id',$data['id'])->update($mainInfo);

            DB::commit();
            return ['code' => 0, 'msg' => 'success', 'data' => ''];
        }
        catch(Exception $e) {
            DB::rollBack();//事务回滚
            Log::debug('编辑销售单:'.var_export($e->getMessage()));
            return ['code' => 1, 'msg' => $e->getMessage(), 'data' => ''];
        }
    }

    //开启批次号编辑
    static public function editWithBatch($mainInfo, $data)
    {
        DB::beginTransaction();
        try {
            $oldSellGoodsInfo = SellGoodsDetailModel::select('id')
                ->where('sell_id', $mainInfo['id'])->get()->toArray();
            $sellGoodsId = [];
            foreach($oldSellGoodsInfo as $sg) {
                $sellGoodsId[] = $sg['id'];
            }

            $oldSellPackageInfo = SellPackageDetailModel::select('id')
                ->where('sell_id', $mainInfo['id'])->get()->toArray();
            $sellPackageId = [];
            foreach($oldSellPackageInfo as $sp) {
                $sellPackageId[] = $sp['id'];
            }

            $oldSellPackageContent = SellPackageContentModel::select('id')
                ->where('sell_id', $mainInfo['id'])->get()->toArray();
            $sellPackageContentId = [];
            foreach($oldSellPackageContent as $spc) {
                $sellPackageContentId[] = $spc['id'];
            }

            $oldSellGoodsDetailBatch = SellGoodsDetailBatchModel::select('id')
                ->where('sell_id', $mainInfo['id'])->get()->toArray();
            $sellGoodsBatchId = [];
            foreach($oldSellGoodsDetailBatch as $gbid) {
                $sellGoodsBatchId[] = $gbid['id'];
            }

            $oldSellGPackageBatch = SellPackageBatchModel::select('id')
                ->where('sell_id', $mainInfo['id'])->get()->toArray();
            $sellPackageBatchId = [];
            foreach($oldSellGPackageBatch as $spid) {
                $sellPackageBatchId[] = $spid['id'];
            }

            $money = 0;//货款金额
            $materielInfo = [];
            $packageInfoArr = [];

            if(!empty($data['goods_info'])) {
                //商品详细添加
                $goodsInfo = json_decode($data['goods_info'],true);
                foreach ($goodsInfo as $key => $value){
                    $money+=($value['price']*$value['num']);

                    $arr = [
                        'materiel_type_id' => $value['materiel_type_id'],
                        'name' => $value['name'],
                        'type_name' => $value['type_name'],
                        'price' => $value['price'],
                        'piece' => empty($value['piece'])?0:$value['piece'],
                        'num' => $value['num'],
                        'image' => $value['image'],
                        'warehouse' => $value['warehouse'],
                        'warehouse_id' => $value['warehouse_id'],
                        'main_id' => $mainInfo['main_id'],
                        'sell_date' => strtotime(date('Y-m-d',strtotime($data['sell_date']))),
                        'sell_id' => $mainInfo['id'],
                        'created_at' => time(),
                    ];
                }
                $sellGoodsDetailId = SellGoodsDetailModel::insertGetId($arr);

                $batchTotalNum = 0;
                foreach($value['batch_info'] as $val) {
                    $batchTotalNum += $val['num'];

                    $batchInfo[] = [
                        'storage_batch_id' => $val['batch_id'],
                        'storage_manage_id' => $val['storage_manage_id'],
                        'sell_goods_detail_id' => $sellGoodsDetailId,
                        'num' => $val['num'],
                        'sell_id' => $mainInfo['id'],
                        'main_id' => $mainInfo['main_id'],
                        'rest_num' => $val['num'],
                        'created_at' => time()
                    ];
                }
                if($value['num'] < $batchTotalNum) {
                    return ['code' => 1, 'msg' => '商品:'.$value['name'].'-'.$value['type_name'].'批次总数量超出商品销售总数', 'data' => ''];
                }

                if($value['num'] > $batchTotalNum) {
                    return ['code' => 1, 'msg' => '商品:'.$value['name'].'-'.$value['type_name'].'批次总数量小于商品销售总数', 'data' => ''];
                }
                SellGoodsDetailBatchModel::insert($batchInfo);
            }

            if(!empty($data['package_info'])) {
                //商品详细添加
                $packageInfo = json_decode($data['package_info'],true);
                foreach ($packageInfo as $k => $val){
                    $money+=($val['price']*$val['num']);
                    $packageInfoArr[$k]['package_id'] = $val['package_id'];
                    $packageInfoArr[$k]['total_cost'] = self::getPackageCost($val['package_id']);
                    $packageInfoArr[$k]['price'] = $val['price'];
                    $packageInfoArr[$k]['sell_id'] = $mainInfo['id'];
//                    $packageInfoArr[$k]['remark'] = $val['remark'];
                    $packageInfoArr[$k]['num'] = $val['num'];
                    $packageInfoArr[$k]['piece'] = empty($val['piece'])?0:$val['piece'];
                    $packageInfoArr[$k]['user_id'] = $mainInfo['user_id'];
                    $packageInfoArr[$k]['main_id'] = $mainInfo['main_id'];
                    $packageInfoArr[$k]['package_content'] = $val['package_content'];
                    $packageInfoArr[$k]['sell_date'] = strtotime(date('Y-m-d',strtotime($data['sell_date'])));
                    $packageInfoArr[$k]['created_at'] = time();
                }

                $arr = [];
                foreach($packageInfoArr as $vv) {
                    $batchNo = $data['batch_title'].date('YmdHis', time()) .mt_rand(10000, 99999).'a';

                    do {
                        $batchNo = $data['batch_title'].date('YmdHis', time()) .mt_rand(10000, 99999).'a';
                    }
                    while(!empty(SellPackageDetailModel::where('package_no', $batchNo)->first()));

                    $packageId = SellPackageDetailModel::insertGetId([
                        'package_id' => $vv['package_id'],
                        'package_no' => $batchNo,
                        'price' => $vv['price'],
                        'total_cost' => $vv['total_cost'],
                        'sell_id' => $vv['sell_id'],
                        'num' => $vv['num'],
                        'piece' => $vv['piece'],
//                        'remark' => $vv['remark'],
                        'user_id' => $mainInfo['user_id'],
                        'main_id' => $mainInfo['main_id'],
                        'sell_date' => $vv['sell_date'],
                        'created_at' => $vv['created_at'],
                    ]);

                    foreach($vv['package_content'] as $vvv) {
                        $packageContentId = SellPackageContentModel::insertGetId([
                            'materiel_class_id' => $vvv['materiel_class_id'],
                            'type_id' => $vvv['type_id'],
                            'storage_id' => $vvv['storage_id'],
                            'package_content_id' => $vvv['id'],
                            'package_id' => $vv['package_id'],
                            'storage_manage_id' => $vvv['storage_manage_id'],
                            'package_detail_id' => $packageId,
                            'sell_id' => $mainInfo['id'],
                            'num' => $vvv['num'],
                            'total_num' => $vvv['num'] * $vv['num'],
                            'user_id' => $mainInfo['user_id'],
                            'main_id' => $mainInfo['main_id'],
                            'created_at' => time()
                        ]);

                        $batchTotalNum = 0;
                        foreach($vvv['batch_info'] as $v) {
                            $batchTotalNum += $v['num'];

                            $arr[] = [
                                'sell_package_content_id' => $packageContentId,
                                'storage_manage_id' => $v['storage_manage_id'],
                                'storage_batch_id' => $v['batch_id'],
                                'num' => $v['num'],
                                'sell_id' => $mainInfo['id'],
                                'main_id' => $mainInfo['main_id'],
                                'rest_num' => $v['num'] * $vv['num'],
                                'created_at' => time()
                            ];
                        }

                        if($batchTotalNum > ($vvv['num'] * $vv['num'])) {
                            return ['code' => 1, 'msg' => '单个套餐内商品数超出对应的商品批次总数', 'data' => ''];
                        }

                        if($batchTotalNum < ($vvv['num'] * $vv['num'])) {
                            return ['code' => 1, 'msg' => '单个套餐内商品数小于对应的商品批次总数', 'data' => ''];
                        }
                    }

                    SellPackageBatchModel::insert($arr);
                }
            }

            //非改价计算价格
            if(!$data['is_zero_suppression'] && $money){
                $finalMoney = 0;
                if(isset($data['discount']) && $data['discount']){//折扣
                    $finalMoney+= ($data['discount']*$money/100);
                }else{
                    $finalMoney = $money;
                }

                if(isset($data['tax_rate']) && $data['tax_rate']){//加税点
                    $finalMoney+= ($data['tax_rate']*$finalMoney/100);
                }

                $mainInfo['final_money'] = $finalMoney;
                $mainInfo['money'] = $money;
            }else{
                $mainInfo['money'] = $money;
            }
            unset($mainInfo['goods_info']);
            unset($mainInfo['package_info']);

            //实收全部结清更新支付状态为全部
//            if(isset($mainInfo['real_money']) && (string)$mainInfo['real_money']==(string)$finalMoney){
//                $mainInfo['pay_status'] =2;
//            }
            //司机更新添加
            if(isset($mainInfo['driver']) && !empty($mainInfo['driver'])){
                $driver = SellDriverModel::where('sell_id',$data['id'])->first();
                if($driver){
                    SellDriverModel::where('sell_id',$data['id'])->update(json_decode($mainInfo['driver'],true));
                }else{
                    $newDriver = json_decode($mainInfo['driver'],true);
                    $newDriver['sell_id'] = $data['id'];
                    $newDriver['main_id'] = $mainInfo['main_id'];
                    SellDriverModel::insert($newDriver);
                }
                unset($mainInfo['driver']);
            }

            //删除旧销售单信息
            SellGoodsDetailModel::whereIn('id', $sellGoodsId)->delete();
            SellPackageDetailModel::whereIn('id', $sellPackageId)->delete();
            SellPackageContentModel::whereIn('id', $sellPackageContentId)->delete();
            SellGoodsDetailBatchModel::whereIn('id', $sellGoodsBatchId)->delete();
            SellPackageBatchModel::whereIn('id', $sellPackageBatchId)->delete();

            //更新销售单
            SellModel::where('id',$data['id'])->update($mainInfo);

            DB::commit();
            return ['code' => 0, 'msg' => 'success', 'data' => ''];
        }
        catch(Exception $e) {
            DB::rollBack();//事务回滚
            Log::debug('编辑销售单:'.var_export($e->getMessage()));
            return ['code' => 1, 'msg' => $e->getMessage(), 'data' => ''];
        }
    }

    static public function exportData($userId, $data)
    {
        $adminInfo = AdminModel::where('id', $userId)->first();

        if($adminInfo['parent_id'] == 0 || $adminInfo['parent_id'] == $userId) {

            $condition['a.main_id'] = ['EQ' => $userId];

        }else {

            $adminAddendumInfo = AdminAddendumModel::select('is_share_sell')->where('main_id',$adminInfo['parent_id'])->first();

            if($adminAddendumInfo['is_share_sell'] == 1) {

                $condition['a.main_id'] = ['EQ' => $adminInfo['parent_id']];
            }else {

                $condition['a.user_id'] = ['EQ' => $userId];
            }
        }

        //搜索类型
        if(!empty($data['keyword'])) {//关键词搜索组是否启用
            switch($data['search_type']) {
                //1->商品名称;2->商品编号
                case 1:
                case 2:
                    $result = self::searchGoodsInfo($condition, $data);
                    break;
                    //搜索内部单号
                case 3:
                    $result = self::searchInnerOrderNo($condition, $data);
                    break;
                    //搜索外部单号
                case 4:
                    $result = self::searchOutOrderNo($condition, $data);
                    break;
                    //搜索快递单号
                case 5:
                    $result = self::searchExpressNo($condition, $data);
                    break;
                    //搜索客户姓名
                case 6:
                    $result = self::searchCustomerName($condition, $data);
                    break;
                    //搜索司机姓名
                case 7:
                    $result = self::searchDriverName($condition, $data);
                    break;
                    //搜索发货人姓名
                case 8:
                    $result = self::searchSenderName($condition, $data);
                    break;
            }
        }
        else {
            return self::searchWithoutKeyword($condition, $data);
        }

        return $result;
    }


    static public function bbbbb($userId, $data)
    {
        //搜索类型
        if(!empty($data['keyword'])) {//关键词搜索组是否启用
            switch($data['search_type']) {
                //1->商品名称;2->商品编号
                case 1:
                case 2:
                    $result = self::searchGoodsInfo($userId, $data);
                    break;
                //搜索内部单号
                case 3:
                    $result = self::searchInnerOrderNo($userId, $data);
                    break;
                //搜索外部单号
                case 4:
                    $result = self::searchOutOrderNo($userId, $data);
                    break;
                //搜索快递单号
                case 5:
                    $result = self::searchExpressNo($userId, $data);
                    break;
                //搜索客户姓名
                case 6:
                    $result = self::searchCustomerName($userId, $data);
                    break;
                //搜索司机姓名
                case 7:
                    $result = self::searchDriverName($userId, $data);
                    break;
                //搜索发货人姓名
                case 8:
                    $result = self::searchSenderName($userId, $data);
                    break;
            }
        }
        else {
            return self::searchWithoutKeyword($userId, $data);
        }

        return $result;
    }

    static private function searchSenderName($userId, $data)
    {
        $condition[] = ['deliver_person', 'like', '%'.$data['keyword'].'%'];
        $sellInfo = SellModel::getSellIdInfo($userId, $data, $condition);

        $sellId = [];
        foreach($sellInfo as $value) {
            $sellId[] = $value['id'];
        }

        return self::commonSearchWithKeyword($userId, $data, $sellId);
    }

    //搜索司机姓名
    static private function searchDriverName($userId, $data)
    {
        //获取用户对应的销售单id
        $sellInfo = SellModel::getSellInfo($userId);

        $sellIdArr = [];
        foreach($sellInfo as $value) {
            $sellIdArr[] = $value['id'];
        }

        $condition['name'] = ['EQ' => $data['keyword']];

        $sellDriverInfo = SellDriverModel::getSellDriverInfo($sellIdArr, $condition);

        $sellId = [];
        foreach($sellDriverInfo as $value) {
            $sellId[] = $value['sell_id'];
        }

        return self::commonSearchWithKeyword($userId, $data, $sellId);
    }

    //内部单号搜索
    static private function searchCustomerName($userId, $data)
    {
        $condition[] = ['name', 'like', '%'.$data['keyword'].'%'];
        $customerIds = SupplierCustomerModel::query()->where($condition)->pluck('id');
        $sellInfo = SellModel::query()->select('id')
        ->from('sell as a')
        ->whereIn('customer_id',$customerIds)
        ->where($userId)->get()->toArray();

        $sellId = [];
        foreach($sellInfo as $value) {
            $sellId[] = $value['id'];
        }

        return self::commonSearchWithKeyword($userId, $data, $sellId);
    }

    //商品信息搜索
    static private function searchGoodsInfo($userId, $data)
    {
        $sellInfo = SellModel::getSellInfo($userId);

        $sellIdArr = [];
        foreach($sellInfo as $value) {
            $sellIdArr[] = $value['id'];
        }

        $condition = [];
        $condition1 = [];
        if($data['search_type'] == 1) {
            $condition[] = ['b.materiel_name', 'like', '%'.$data['keyword'].'%'];
            $condition1[] = ['materiel_name', 'like', '%'.$data['keyword'].'%'];
        }
        else if($data['search_type'] == 2) {
            $condition[] = ['b.materiel_no', 'like', '%'.$data['keyword'].'%'];
            $condition1[] = ['materiel_no', 'like', '%'.$data['keyword'].'%'];
        }

        $sellDetailSellIdInfo = SellGoodsDetailModel::getGoodsDetailInfo($sellIdArr, $condition);

        //查找销售单套餐内指定商品的的信息-商品id
        $sellPackageContentInfo = SellPackageContentModel::getSellPackageContent($userId, $condition1);

        $sellIdArr = [];
        foreach($sellDetailSellIdInfo as $value) {
            $sellIdArr[] = $value['sell_id'];
        }

        //获取商品信息和套餐内商品信息的销售单id集合
        foreach($sellPackageContentInfo as $val) {
            if(!in_array($val['sell_id'], $sellIdArr)) {
                array_push($sellIdArr, $val['sell_id']);
            }
        }

        return self::commonSearchWithKeyword($userId, $data, $sellIdArr);
    }

    //内部单号搜索
    static private function searchInnerOrderNo($userId, $data)
    {
        $condition[] = ['order_no', 'like', '%'.$data['keyword'].'%'];
        $sellInfo = SellModel::getSellIdInfo($userId, $data, $condition);

        $sellId = [];
        foreach($sellInfo as $value) {
            $sellId[] = $value['id'];
        }

        return self::commonSearchWithKeyword($userId, $data, $sellId);
    }

    //外部单号搜索
    static private function searchOutOrderNo($userId, $data)
    {
        $condition[] = ['out_order_no', 'like', '%'.$data['keyword'].'%'];
        $sellInfo = SellModel::getSellIdInfo($userId, $data, $condition);

        $sellId = [];
        foreach($sellInfo as $value) {
            $sellId[] = $value['id'];
        }

        return self::commonSearchWithKeyword($userId, $data, $sellId);
    }

    //快递单号检索
    static private function searchExpressNo($userId, $data)
    {
        $condition[] = ['logistics_order_no', 'like', '%'.$data['keyword'].'%'];
        $sellInfo = SellModel::getSellIdInfo($userId, $data, $condition);

        $sellId = [];
        foreach($sellInfo as $value) {
            $sellId[] = $value['id'];
        }

        return self::commonSearchWithKeyword($userId, $data, $sellId);
    }

    //使用关键词检索
    static private function commonSearchWithKeyword($userId, $data, $sellIdArr)
    {
        $query = SellModel::select(
            'a.*',
            'b.username',
            'b.nickname'
        )
            ->from('sell as a')
            ->leftJoin('admin as b', 'b.id', '=', 'a.user_id')
            ->with('materielInfo', function($query) {
                $query->select(
                    'sell_goods_detail.id as sell_goods_id',
                    'a.materiel_name as name',
                    'a.type_name',
                    'a.materiel_no',
                    'a.materiel_img as image',
                    'price',
                    'sell_goods_detail.num',
                    'b.storage_name as warehouse',
                    'b.id as warehouse_id',
                    'piece',
                    'sell_goods_detail.materiel_type_id',
                    'sell_goods_detail.sell_id',
                    'cost_price',
                )->leftJoin('materiel_type as a', 'a.id', '=', 'sell_goods_detail.materiel_type_id')
                    ->leftJoin('storage as b', 'b.id', '=', 'sell_goods_detail.warehouse_id');
            })
            ->with('packageInfo', function($query) {
                $query->select(
                    'sell_package_detail.id as sell_package_id',
                    'package_id',
                    'package_name',
                    'price',
                    'total_cost',
                    'sell_id',
                    'num',
                    'out_num',
                )
                    ->leftJoin('package as p', 'p.id', '=', 'sell_package_detail.package_id')
                    ->with('packageContent', function($query) {
                        $query->select(
                            'sell_package_content.id as sell_package_content_id',
                            'sell_package_content.num',
                            'sell_package_content.materiel_type_id',
                            'package_detail_id',
                            'mt.materiel_name',
                            'mt.type_name',
                            'mt.materiel_no',
                            'mt.materiel_img',
                            'mt.cost',
                            'mcs.class_name as s_class_name',
                            'mcs.class_no as s_class_no',
                            'mcf.class_name as f_class_name',
                            'mcf.class_no as f_class_no',
                            's.storage_name',
                            'sm.in_storage_num'
                        )
                            ->leftJoin('materiel_type as mt', 'mt.id', '=', 'sell_package_content.materiel_type_id')
                            ->leftJoin('materiel_class as mcs', 'mcs.id', '=', 'sell_package_content.materiel_class_id')
                            ->leftJoin('materiel_class as mcf', 'mcf.id', '=', 'mcs.parent_id')
                            ->leftJoin('storage_manage as sm', 'sm.id', '=', 'sell_package_content.storage_manage_id')
                            ->leftJoin('storage as s', 's.id', '=', 'sell_package_content.storage_id');
                    });
            })
            ->with('driverInfo', function($query) {
                $query->select(
                    'id',
                    'plate_number',
                    'name',
                    'phone',
                    'logistics_company',
                    'remark',
                    'plate_image',
                    'id_card_image',
                    'driving_licence',
                    'sell_id',
                );
            })
            ->where([
                'repeal_status' => $data['repeal_status']
            ])
            ->where($userId);

        if(!empty($data['start_time'])) {
            $startTimeArr = explode(' ', $data['start_time']);
            $startTime = strtotime($startTimeArr[0].' 00:00:00');
        }

        if(!empty($data['end_time'])) {
            $endTimeArr = explode(' ', $data['end_time']);
            $endTime = strtotime($endTimeArr[0].' 23:59:59');
        }

        if(!empty($startTime) && !empty($endTime)) {
            $query->whereBetween('sell_time', [$startTime, $endTime]);
        }
        else if(!empty($startTime) && empty($endTime)) {
            $query->where('sell_time', '>=', $startTime);
        }
        else if(empty($startTime) && !empty($endTime)) {
            $query->where('sell_time', '<=', $endTime);
        }

        //销售单状态
        switch($data['status']) {
            //新订单
            case 1:
                $query->where('out_status', 0);
                $query->where('pay_status', 0);
                break;
            //已收款
            case 2:
                $query->whereIn('pay_status', [1,2]);
                $query->where('out_status', 0);
                break;
            //已完结
            case 3:
                $query->where('out_status', 2);
                $query->where('pay_status', 2);
                break;
            //已出库
            case 4:
                $query->where('pay_status', 0);
                $query->whereIn('out_status', [1,2]);
                break;
            //预出库(未付款)
            case 5:
                $query->where('prepare_out_status', 1);
                $query->where('pay_status', 0);
                break;
            //预出库(未付款)
            case 6:
                $query->where('prepare_out_status', 1);
                $query->whereIn('pay_status', [1,2]);
                break;
        }

        $query =  $query->whereIn('a.id', $sellIdArr)
            ->orderBy('a.id','desc');

        if(!empty($data['currentPage'])){

            $query =  $query->paginate($data['pageSize'],['*'], '',$data['currentPage'])->toArray();

        }else{
            $query =  $query->toArray();
        }

        foreach($query['data'] as &$value) {
            foreach($value['materiel_info'] as $k => $val) {
                $storageManageInfo = StorageManageModel::where('type_id', $val['materiel_type_id'])
                    ->where('storage_id', $val['warehouse_id'])->first();

                $value['materiel_info'][$k]['storage_manage_id'] = $storageManageInfo['id'];
                $value['materiel_info'][$k]['in_storage_num'] = $storageManageInfo['in_storage_num'];
            }
        }

        return $query;
    }

    static private function searchWithoutKeyword($userId, $data)
    {
        DB::enableQueryLog();
        $query = SellModel::select(
            'a.*',
            'b.username',
            'b.nickname'
        )
            ->from('sell as a')
            ->leftJoin('admin as b', 'b.id', '=', 'a.user_id')
            ->with('materielInfo', function($query) {
                $query->select(
                    'a.materiel_name as name',
                    'a.type_name',
                    'a.materiel_no',
                    'a.materiel_img as image',
                    'price',
                    'sell_goods_detail.num',
                    'b.storage_name as warehouse',
                    'b.id as warehouse_id',
                    'piece',
                    'sell_id',
                    'cost_price',
                    'sell_goods_detail.materiel_type_id',
                    'sell_goods_detail.shelf_id',
                    'sell_goods_detail.location_id',
                    'se.shelf_name',
                    'lo.location_name',
                    'a.is_product_materiel'
                )->leftJoin('materiel_type as a', 'a.id', '=', 'sell_goods_detail.materiel_type_id')
                ->leftJoin('storage as b', 'b.id', '=', 'sell_goods_detail.warehouse_id')
                ->leftJoin('storage_shelf as se','sell_goods_detail.shelf_id','=','se.id')
                ->leftJoin('storage_shelf_location as lo','sell_goods_detail.location_id','=','lo.id')
             /*    ->with('content',function($query){
                    $query->select(
                    'materiel_product_content.id',
                    'a.materiel_name',
                    'a.type_name',
                    'a.materiel_img',
                    'a.materiel_no',
                    'product_id',
                    'materiel_product_content.num',
                    'materiel_product_content.price',
                    'materiel_product_content.total_price',
                )->leftJoin('materiel_type as a', 'a.id', '=', 'materiel_product_content.type_id');
                })*/;
            })
            ->with('packageInfo', function($query) {
                $query->select(
                    'sell_package_detail.id',
                    'package_id',
                    'package_name',
                    'price',
                    'total_cost',
                    'sell_id',
                    'num',
                    'out_num',
                )
                    ->leftJoin('package as p', 'p.id', '=', 'sell_package_detail.package_id')
                    ->with('packageContent', function($query) {
                        $query->select(
                            'sell_package_content.id',
                            'sell_package_content.num',
                            'sell_package_content.materiel_type_id',
                            'package_detail_id',
                            'mt.materiel_name',
                            'mt.type_name',
                            'mt.materiel_no',
                            'mt.materiel_img',
                            'mcs.class_name as s_class_name',
                            'mcs.class_no as s_class_no',
                            'mcf.class_name as f_class_name',
                            'mcf.class_no as f_class_no',
                            's.storage_name',
                            'sm.in_storage_num',
                            'sell_package_content.shelf_id',
                            'sell_package_content.location_id',
                            'se.shelf_name',
                            'lo.location_name',

                        )
                            ->leftJoin('materiel_type as mt', 'mt.id', '=', 'sell_package_content.materiel_type_id')
                            ->leftJoin('materiel_class as mcs', 'mcs.id', '=', 'sell_package_content.materiel_class_id')
                            ->leftJoin('materiel_class as mcf', 'mcf.id', '=', 'mcs.parent_id')
                            ->leftJoin('storage_manage as sm', 'sm.id', '=', 'sell_package_content.storage_manage_id')
                            ->leftJoin('storage as s', 's.id', '=', 'sell_package_content.storage_id')
                            ->leftJoin('storage_shelf as se','sell_package_content.shelf_id','=','se.id')
                            ->leftJoin('storage_shelf_location as lo','sell_package_content.location_id','=','lo.id');
                    });
            })
            ->with('driverInfo', function($query) {
                $query->select(
                    'id',
                    'plate_number',
                    'name',
                    'phone',
                    'logistics_company',
                    'remark',
                    'plate_image',
                    'id_card_image',
                    'driving_licence',
                    'sell_id',
                );
            })
            ->where([
                'repeal_status' => $data['repeal_status']
            ])
            ->where('a.delete_flag',0)
            ->where($userId);

        if(!empty($data['start_time'])) {
            $startTimeArr = explode(' ', $data['start_time']);
            $startTime = strtotime($startTimeArr[0].' 00:00:00');
        }

        if(!empty($data['end_time'])) {
            $endTimeArr = explode(' ', $data['end_time']);
            $endTime = strtotime($endTimeArr[0].' 23:59:59');
        }

        if(!empty($startTime) && !empty($endTime)) {
            $query->whereBetween('sell_time', [$startTime, $endTime]);
        }
        else if(!empty($startTime) && empty($endTime)) {
            $query->where('sell_time', '>=', $startTime);
        }
        else if(empty($startTime) && !empty($endTime)) {
            $query->where('sell_time', '<=', $endTime);
        }

        //销售单状态
        switch($data['status']) {
            //新订单
            case 1:
                $query->where('out_status', 0);
                $query->where('pay_status', 0);
                break;
            //已收款
            case 2:
                $query->whereIn('pay_status', [1,2]);
                $query->where('out_status', 0);
                break;
            //已完结
            case 3:
                $query->where('out_status', 2);
                $query->where('pay_status', 2);
                break;
            //已出库
            case 4:
                $query->where('pay_status', 0);
                $query->whereIn('out_status', [1,2]);
                break;
            //预出库(未付款)
            case 5:
                $query->where('prepare_out_status', 1);
                $query->where('pay_status', 0);
                break;
            //预出库(已付款)
            case 6:
                $query->where('prepare_out_status', 1);
                $query->whereIn('pay_status', [1,2]);
                break;
        }

        if(!empty($data['currentPage'])){

            $query =  $query->orderBy('a.id','desc')->paginate($data['pageSize'],['*'], '',$data['currentPage'])->toArray();

        }else{
            $query = $query->orderBy('a.id','desc')->get()->toArray();
        }

    if(!empty($query['data'])){
            foreach($query['data'] as &$value) {
                if(!empty($value['materiel_info'])){
                    foreach($value['materiel_info'] as $k => $val) {
        //                $storageManageInfo = StorageManageModel::where('type_id', $val['materiel_type_id'])
        //                    ->where('storage_id', $val['warehouse_id'])->first();

                        $storageManageInfo = StorageManageModel::where('type_id', $val['materiel_type_id'])
                            ->where('storage_id', $val['warehouse_id'])->where(['shelf_id'=>$val['shelf_id'],'location_id'=>$val['location_id']])->first();
                        if(!empty($storageManageInfo)){
                            $value['materiel_info'][$k]['in_storage_num'] = $storageManageInfo['in_storage_num'];

                        }else{
                            $value['materiel_info'][$k]['in_storage_num'] = 0;

                        }
                    }
                }
            }
    }
        return $query;
    }

    static public function detail02($id)
    {
        $result = SellModel::detail02($id)->toArray();

        $result['piece'] = 0;
        if(!empty($result['materiel_info'])) {
            foreach($result['materiel_info'] as &$value) {
                if($value['location_id'] != 0) {
                    $storageManageInfo = StorageManageModel::where('type_id', $value['materiel_type_id'])
                    ->where('storage_id', $value['warehouse_id'])->where(['shelf_id'=>$value['shelf_id'],'location_id'=>$value['location_id']])->first();
                }
                else {
                    $storageManageInfo = StorageManageModel::where('type_id', $value['materiel_type_id'])
                    ->where('storage_id', $value['warehouse_id'])->first();
                }

                //没有传货架库位，使用默认货架库位
                if(empty($value['shelf_id']) || empty($value['location_id'])){

                    $sfData = ShelfService::get_default($value['warehouse_id']);
                    if(!empty($sfData)){
                        $shelf_id = $sfData['id'];
                        $lData = ShelfService::get_default($shelf_id,2);
                        $location_id = $lData['id'];
                    }else{
                        $shelf_id = 0;
                        $location_id = 0;
                        $value['shelf_id'] = 0;
                        $value['location_id'] = 0;
                    }
                }else{
                    $shelf_id = $value['shelf_id'];
                    $location_id = $value['location_id'];
                }

                $value['storage_manage_id'] = $storageManageInfo['id'];
                $value['materiel_class_id'] = $storageManageInfo['materiel_class_id'];
                $value['in_storage_num'] = $storageManageInfo['in_storage_num'];
                $returnData = SalesReturnModel::select(DB::raw('SUM(num) as total_return_num'))
                ->from('sales_return as a')
                ->leftJoin('sales_return_goods_detail as b','b.return_id','=','a.id')
                ->where(['sell_id' => $value['sell_id'],'b.materiel_type_id' => $value['materiel_type_id']])
                ->where(['repeal_status' => 0,'delete_flag' => 0])->first()->toArray();
                $value['return_num'] = $value['num'] - $returnData['total_return_num'];
                $result['piece'] += $value['piece'];
                if($value['is_product_materiel'] == 0){
                    if($value['is_use_serial'] == 1){
                        $value['is_use_serial']  = 1;
                        $scondition['goods_id']   = $value['materiel_type_id'];
                        $scondition['a.storage_manage_id'] = $storageManageInfo['id'];
                        $slist = SerialNumberModel::select('serial_no')
                                ->from('serial_number as a')
                                ->leftJoin('sell_goods_detail as b' ,'a.goods_id','=','b.materiel_type_id')
                                ->where('sell_id',$value['sell_id'])
                                ->where($scondition)->where('status',0)->get()->toArray();
                        $value['serial_number_list']  = array_map('array_shift',$slist);
                    }else{
                        $value['is_use_serial'] = 0;
                        $value['serial_number_list'] = [];
                    }
                }else{
                   $value['serial_number_list'] = [];
                }


            }
        }

        if(!empty($result['package_info'])) {
            foreach($result['package_info'] as $key=>$val) {
                $result['package_info'][$key]['piece'] += $val['piece'];

                foreach ($val['package_content'] as $pk =>$pv){

                    if($pv['is_use_serial'] ==1){

                        $result['package_info'][$key]['package_content'][$pk]['is_use_serial']  = $pv['is_use_serial'];
                        $scondition['goods_id']   = $pv['materiel_type_id'];
                        $scondition['a.storage_manage_id'] = $pv['storage_manage_id'];
                        $slist = SerialNumberModel::select('serial_no')
                        ->from('serial_number as a')
                        ->leftJoin('sell_package_content as b' ,'a.goods_id','=','b.materiel_type_id')
                        ->where('sell_id',$val['sell_id'])
                        ->where($scondition)->where('status',0)->get()->toArray();
                        $result['package_info'][$key]['package_content'][$pk]['serial_number_list']  =array_map('array_shift',$slist);
                    }else{
                        $result['package_info'][$key]['package_content'][$pk]['is_use_serial'] = 0;
                        $result['package_info'][$key]['package_content'][$pk]['serial_number_list'] = [];
                    }

                }
            }
        }

        return $result;
    }

    static public function detail1($id)
    {
        $result = SellModel::detail($id)->toArray();

        $result['piece'] = 0;
        if(!empty($result['materiel_info'])) {
            foreach($result['materiel_info'] as &$value) {
                if($value['location_id'] != 0) {
                    $storageManageInfo = StorageManageModel::where('type_id', $value['materiel_type_id'])
                        ->where('storage_id', $value['warehouse_id'])->where(['shelf_id'=>$value['shelf_id'],'location_id'=>$value['location_id']])->first();
                }
                else {
                    $storageManageInfo = StorageManageModel::where('type_id', $value['materiel_type_id'])
                        ->where('storage_id', $value['warehouse_id'])->first();
                }

//                $storageManageInfo = StorageManageModel::where('type_id', $value['materiel_type_id'])
//                    ->where('storage_id', $value['warehouse_id'])->first();

                //没有传货架库位，使用默认货架库位
                if(empty($value['shelf_id']) || empty($value['location_id'])){
                  /*   $shelf_id = ShelfService::get_default($value['warehouse_id'])['id'];
                    $location_id = ShelfService::get_default($shelf_id,2)['id']; */

                    $sfData = ShelfService::get_default($value['warehouse_id']);
                    if(!empty($sfData)){
                        $shelf_id = $sfData['id'];
                        $lData = ShelfService::get_default($shelf_id,2);
                        $location_id = $lData['id'];
                    }else{
                        $shelf_id = 0;
                        $location_id = 0;
                        $value['shelf_id'] = 0;
                        $value['location_id'] = 0;
                    }
                }else{
                    $shelf_id = $value['shelf_id'];
                    $location_id = $value['location_id'];
                }

                if($value['is_product_materiel']) {
                    $productContentInfo = MaterielProductContentModel::where('product_id', $value['materiel_type_id'])->get()->toArray();
                    if($value['calc_ratio'] != 0) {
                        foreach($productContentInfo as $kk => $productVal) {

                        }
                    }
                    else {
                        $value['product_content_info'] = $productContentInfo;
                    }
                }
                else {
                    $value['product_content_info'] = [];
                }

                $value['storage_manage_id'] = $storageManageInfo['id'];
                $value['materiel_class_id'] = $storageManageInfo['materiel_class_id'];
                $value['in_storage_num'] = $storageManageInfo['in_storage_num'];

                $result['piece'] += $value['piece'];
                if($value['is_use_serial'] ==1){
                    $value['is_use_serial']  = 1;
                    $scondition['goods_id']   = $value['materiel_type_id'];
                    $scondition['a.storage_manage_id'] = $storageManageInfo['id'];
                    $slist = SerialNumberModel::select('serial_no')
                    ->from('serial_number as a')
                    ->leftJoin('sell_goods_detail as b' ,'a.goods_id','=','b.materiel_type_id')
                   ->where('sell_id',$value['sell_id'])
                    ->where($scondition)->where('status',0)->get()->toArray();
                    $value['serial_number_list']  = array_map('array_shift',$slist);
                }else{
                    $value['is_use_serial'] = 0;
                    $value['serial_number_list'] = [];
                }
            }
        }

        if(!empty($result['package_info'])) {
            foreach($result['package_info'] as $key=>$val) {
                $result['package_info'][$key]['piece'] += $val['piece'];

                foreach ($val['package_content'] as $pk =>$pv){

                    if($pv['is_use_serial'] ==1){

                        $result['package_info'][$key]['package_content'][$pk]['is_use_serial']  = $pv['is_use_serial'];
                        $scondition['goods_id']   = $pv['materiel_type_id'];
                        $scondition['a.storage_manage_id'] = $pv['storage_manage_id'];
                        $slist = SerialNumberModel::select('serial_no')
                        ->from('serial_number as a')
                        ->leftJoin('sell_package_content as b' ,'a.goods_id','=','b.materiel_type_id')
                        ->where('sell_id',$val['sell_id'])
                        ->where($scondition)->where('status',0)->get()->toArray();
                        $result['package_info'][$key]['package_content'][$pk]['serial_number_list']  =array_map('array_shift',$slist);
                    }else{
                        $result['package_info'][$key]['package_content'][$pk]['is_use_serial'] = 0;
                        $result['package_info'][$key]['package_content'][$pk]['serial_number_list'] = [];
                    }

                }
            }
        }

        return $result;
    }

    //重新下单
    static public function addAgain($data)
    {
        DB::beginTransaction();

        try {
            //销售单新增
            $sell = SellModel::find($data['id'])->toArray();

            $sellTime = strtotime(date('Y-m-d', strtotime($sell['sell_date'])));

            unset($sell['id']);
            unset($sell['updated_at']);
            $sell['user_id'] = $data['user_id'];
            $sell['repeal_status'] = 0;
            $sell['real_money'] = 0;
            $sell['out_status'] = 0;
            $sell['pay_status'] = 0;
            $sell['has_product_order'] = 0;
            $sell['order_no'] = 'S'. $data['main_id'].TimeUtil::getMillisecond();//订单号
            $sell['created_at'] =time();
            $sell['sell_date'] = time();
            $sell['sell_time'] = $sellTime;
            $sell['deliver_time'] = strtotime($sell['deliver_time']);
            $sell['order_time'] = strtotime($sell['order_time']);

            $mainId = SellModel::insertGetId($sell);
            //商品详细
            $sellGoods = SellGoodsDetailModel::select('id', 'materiel_type_id','name','type_name','price','num','image','warehouse','warehouse_id','main_id','materiel_no')->where('sell_id',$data['id'])->get()->toArray();
            if(!empty($sellGoods)){
                foreach ($sellGoods as $val){
                    $val['sell_id'] = $mainId;
                    $val['created_at'] =  time();
                    $sellGoodsId = $val['id'];

                    unset($val['id']);
                    SellGoodsDetailModel::insertGetId($val);
                }

//                SellGoodsDetailBatchModel::insert($newdetaiBatchInfo);
            }

            //销售单套餐信息
            $sellPackage = SellPackageDetailModel::select(
                'id','package_id', 'price', 'num', 'pay_status','sell_date'
            )
                ->where('sell_id',$data['id'])->get()->toArray();
            if(!empty($sellPackage)) {
                $packageContentBatch = [];
                $newdetaiBatchInfo = [];
                $batchNo = $data['batch_title'].date('YmdHis', time()) .mt_rand(1000, 9999).'1';

                do {
                    $batchNo = $data['batch_title'].date('YmdHis', time()) .mt_rand(1000, 9999).'1';
                }
                while(!empty(SellPackageDetailModel::where('package_no', $batchNo)->first()));
                foreach ($sellPackage as $values) {
                    $packageGoodsDetailId = $values['id'];
                    unset($values['id']);
                    $values['package_no'] = $batchNo;
                    $values['sell_date'] = time();
                    $values['user_id'] = $data['user_id'];
                    $values['main_id'] = $data['main_id'];
                    $values['sell_id'] = $mainId;
                    $values['created_at'] =  time();

                    $newSellPackageId = SellPackageDetailModel::insertGetId($values);

                    $packageContent = SellPackageContentModel::select(
                        'id',
                        'materiel_class_id',
                        'materiel_type_id',
                        'storage_id',
                        'package_content_id',
                        'storage_manage_id',
                        'package_id',
                        'num',
                        'total_num'
                    )->where([
                        'sell_id' => $data['id'],
                        'package_detail_id' => $packageGoodsDetailId
                    ])
                        ->get()->toArray();

                    if(!empty($packageContent)) {
                        foreach($packageContent as $vals) {
                            $arr = [
                                'materiel_class_id' => $vals['materiel_class_id'],
                                'materiel_type_id' => $vals['materiel_type_id'],
                                'storage_id' => $vals['storage_id'],
                                'package_id' => $vals['package_id'],
                                'package_content_id' => $vals['package_content_id'],
                                'storage_manage_id' => $vals['storage_manage_id'],
                                'package_detail_id' => $newSellPackageId,
                                'sell_id' => $mainId,
                                'num' => $vals['num'],
                                'total_num' => $vals['total_num'],
                                'rest_num' => $vals['total_num'],
                                'user_id' => $data['user_id'],
                                'main_id' => $data['main_id'],
                                'created_at' => time()
                            ];

                            $sellPackageContentId = SellPackageContentModel::insertGetId($arr);

//                            $sellPackageContentInfo = SellPackageBatchModel::where('sell_package_content_id', $vals['id'])->get()->toArray();
//                            foreach($sellPackageContentInfo as $vv1) {
//                                $packageContentBatch[] = [
//                                    'sell_package_content_id' => $sellPackageContentId,
//                                    'storage_manage_id' => $vv1['storage_manage_id'],
//                                    'storage_batch_id' => $vv1['storage_manage_id'],
//                                    'sell_id' => $mainId,
//                                    'main_id' => $vv1['main_id'],
//                                    'num' => $vv1['num'],
//                                    'rest_num' => $vv1['num'],
//                                    'created_at' => time()
//                                ];
//                            }
                        }
                    }
                }

                SellPackageBatchModel::insert($packageContentBatch);
            }

            //司机
            $sellDriver = SellDriverModel::select('plate_number','name','phone','logistics_company','remark','plate_image','id_card_image','driving_licence','main_id')->where('sell_id',$data['id'])->first();
            if($sellDriver){
                $sellDriver = json_decode(json_encode($sellDriver),true);
                $sellDriver['sell_id'] = $mainId;
                $sellDriver['created_at'] = time();
                SellDriverModel::insert($sellDriver);
            }
            //其他费用
            $sellOtherCharges = SellOtherChargesModel::select('money','other_type_name','other_remark','main_id')->where('sell_id',$data['id'])->get()->toArray();
            if($sellOtherCharges){
                foreach ($sellOtherCharges as &$value1){
                    $value1['sell_id'] = $mainId;
                    $value1['created_at'] =  time();
                }
                SellOtherChargesModel::insert($sellOtherCharges);
            }

            DB::commit();
            return ['code' => 0, 'msg' => 'success', 'data' => ''];
        }
        catch(Exception $e) {
            DB::rollBack();
            Log::debug('销售单-重新下单:'.var_export($e->getMessage(), true));
            return ['code' => 1, 'msg' => $e->getMessage(), 'data' => ''];
        }
    }

    static private function getPackageCost($packageId)
    {
        $packageTotalCost = PackageContentModel::select(
            'a.num',
            'b.materiel_mean_cost'
        )
            ->from('package_content as a')
            ->leftJoin('storage_manage as b', 'b.id', '=', 'a.storage_manage_id')
            ->where('a.package_id', $packageId)
            ->where('a.delete_flag', 0)
            ->where('b.delete_flag', 0)
            ->first();

        return $packageTotalCost['num'] * $packageTotalCost['materiel_mean_cost'];
    }

    //获取销售单套餐成本
    public static function detail($id)
    {
        $sellInfo = SellModel::getSellMainInfo($id);

        if(empty($sellInfo)) {
            return ['code' => 0, 'msg' => 'success', 'data' => ''];
        }

        $goodsInfo = SellGoodsDetailModel::detail($id);

        if(empty($goodsInfo)) {
            $sellInfo['materiel_info'] = [];
        }
        else {
            $sellGoodsDetail = [];
            foreach($goodsInfo as $key => $materielValue) {
                if($materielValue['location_id'] != 0) {
                    $storageManageInfo = StorageManageModel::where([
                        'type_id' => $materielValue['materiel_type_id'],
                        'storage_id' => $materielValue['warehouse_id'],
                        'location_id'=> $materielValue['location_id']
                    ])
                        ->first();
                }
                else {
                    $storageManageInfo = StorageManageModel::where('type_id', $materielValue['materiel_type_id'])
                        ->where('storage_id', $materielValue['warehouse_id'])->first();
                }

                $sellSerialInfo = SellOutSerialNumbersModel::select('serial_number')->where([
                    'sell_id' => $id,
                    'type_id' => $materielValue['materiel_type_id']
                ])->get()->toArray();

                $sellSerialData = [];
                foreach($sellSerialInfo as $serialInfoVal) {
                    $sellSerialData[] = $serialInfoVal['serial_number'];
                }

                $materielImg = '';
                if(!empty($materielValue['image'])) {
                    $materielImgArr = array_filter(explode(',', $materielValue['image']), function($v) { return $v !== ''; });

                    $materielImg = $materielImgArr[0];
                }

                if($materielValue['is_product_materiel']) {
                    $materielContentId = MaterielProductContentModel::where('product_id', $materielValue['materiel_type_id'])
                        ->pluck('type_id');
                }
                else {
                    $materielContentId = [];
                }

                $sellGoodsDetail[$key] = [
                    'sell_goods_id' => $materielValue['sell_goods_id'],
                    'materiel_unit' => $materielValue['materiel_unit'],
                    'is_product_materiel' => $materielValue['is_product_materiel'],
                    'materiel_type_id' => $materielValue['materiel_type_id'],
                    'serial_number_list' => $sellSerialData,
                    'name' => $materielValue['name'],
                    'type_name' => $materielValue['type_name'],
                    'price' => $materielValue['price'],
                    'cost_price' => $materielValue['cost_price'],
                    'num' => $materielValue['num'],
                    'out_num' => $materielValue['out_num'],
                    'materiel_no' => $materielValue['materiel_no'],
                    'image' => empty($materielImg)?'':$materielImg,
                    'warehouse' => $materielValue['warehouse'],
                    'warehouse_id' => $materielValue['warehouse_id'],
                    'piece' => $materielValue['piece'],
                    'sell_id' => $materielValue['sell_id'],
                    'materiel_class_id' => $materielValue['materiel_class_id'],
                    'shelf_id' => $materielValue['shelf_id'],
                    'location_id' => $materielValue['location_id'],
                    'shelf_name' => empty($materielValue['shelf_name'])?'':$materielValue['shelf_name'],
                    'location_name' => empty($materielValue['location_name'])?'':$materielValue['location_name'],
                    'storage_manage_id' => empty($storageManageInfo)?0:$storageManageInfo['id'],
                    'in_storage_num' => empty($storageManageInfo)?0:$storageManageInfo['in_storage_num'],
                    'goods_batch_info' => $materielValue['goods_batch_info'],
                    'is_use_serial' => $materielValue['is_use_serial'],
                    'content_type_id' => $materielContentId
                ];
            }

            $sellInfo['materiel_info'] = $sellGoodsDetail;
        }

        $packageInfo = SellPackageDetailModel::detail($id);

        if(empty($packageInfo)) {
            $sellInfo['package_info'] = [];
        }
        else {
            $sellInfo['package_info'] = $packageInfo;
        }

        $productOrderInfo = ProductOrderModel::where([
            'product_source' => 1,
            'product_source_id' => $id,
            'is_cancel' => 0,
            'delete_flag' => 0
        ])->first();

        if(empty($productOrderInfo)) {
            $sellInfo['has_product_order'] = 0;
            $sellInfo['product_order_id'] = 0;
            $sellInfo['product_no'] = "";
            $sellInfo['product_status'] = 0;
        }
        else {
            $sellInfo['has_product_order'] = 1;
            $sellInfo['product_order_id'] = $productOrderInfo['id'];
            $sellInfo['product_no'] = $productOrderInfo['product_no'];
            $sellInfo['product_status'] = $productOrderInfo['product_status'];
        }

        return ['code' => 0, 'msg' => '', 'data' => $sellInfo];
    }

    public static function list(array $userId, array $data)
    {
        //搜索类型
        if(!empty($data['keyword'])) {//关键词搜索组是否启用
            switch($data['search_type']) {
                //1->商品名称;2->商品编号
                case 1:
                case 2:
                    $result = SELF::searchGoodsInfo($userId, $data);
                    break;
                //搜索内部单号
                case 3:
                    $result = SELF::searchInnerOrderNo($userId, $data);
                    break;
                //搜索外部单号
                case 4:
                    $result = SELF::searchOutOrderNo($userId, $data);
                    break;
                //搜索快递单号
                case 5:
                    $result = SELF::searchExpressNo($userId, $data);
                    break;
                //搜索客户姓名
                case 6:
                    $result = SELF::searchCustomerName($userId, $data);
                    break;
                //搜索司机姓名
                case 7:
                    $result = SELF::searchDriverName($userId, $data);
                    break;
                //搜索发货人姓名
                case 8:
                    $result = SELF::searchSenderName($userId, $data);
                    break;
            }
        }
        else {
            $result = SELF::searchWithoutKeyword($userId, $data);
        }

        foreach($result['data'] as &$value) {
            $productInfo = ProductOrderModel::where([
                'product_source' => 1,
                'product_source_id' => $value['id'],
                'is_cancel' => 0,
                'delete_flag' => 0
            ])->first();

            if(empty($productInfo)) {
                $value['has_product_order'] = 0;
                $value['product_no'] = '';
            }
            else {
                $value['has_product_order'] = 1;
                $value['product_no'] = $productInfo['product_no'];
            }
        }

        return $result;
    }

    public static function sellSerialList(array $data)
    {
        if(!empty($data['id'])) {
            $sellInfo = SellModel::where(['id'=>$data['id']])->first();

            if($sellInfo['out_status'] != 2){
                return ['code'=>1,'msg'=>'销售单号：'.$sellInfo['order_no'].'，还没有全部出库，不能选择序列号！','data'=>''];
            }
        }

        $serialInfo = SerialNumberModel::select(
            'a.id as serial_id',
            'a.serial_no as serial_number',
            'b.materiel_name',
            'b.type_name',
            'b.id as type_id',
            'a.storage_manage_id'
        )
            ->from('serial_number as a')
            ->leftJoin('materiel_type as b', 'b.id', '=', 'a.goods_id')
            ->where([
                'package_id' => $data['type_id'],
                'sell_id' => $data['id'],
                'status' => 0
            ])->get()->toArray();

        $arr = [];
        if(!empty($serialInfo)) {
            foreach($serialInfo as $value) {
                $arr[$value['type_id']]['type_id'] = $value['type_id'];
                $arr[$value['type_id']]['materiel_name'] = $value['materiel_name'];
                $arr[$value['type_id']]['type_name'] = $value['type_name'];
                $productContentInfo = MaterielProductContentModel::where([
                    'type_id' => $value['type_id'],
                    'product_id' => $data['type_id'],
                ])
                    ->first();

                $arr[$value['type_id']]['num'] = $productContentInfo['num'];
                $arr[$value['type_id']]['serial_info'][] = [
                    'serial_id' => $value['serial_id'],
                    'serial_no' => $value['serial_number'],
                    'storage_manage_id' => $value['storage_manage_id'],
                ];
            }
        }

        return array_values($arr);
    }

    public static function sellSerialList2(array $data)
    {
        //获取所有套件内容
        $contentInfo = MaterielProductContentModel::where('product_id', $data['type_id'])
            ->get()->toArray();

        $productContentTypeId = [];//套件商品id
        foreach($contentInfo as $value) {
            $productContentTypeId[] = $value['type_id'];
        }

        //获取销售单已使用的序列号
        $getSellSerialInfo = SellOutSerialNumbersModel::select(
            'a.serial_number',
            'a.serial_id',
            'b.materiel_name',
            'b.type_name',
            'b.materiel_no',
            'b.materiel_name',
            'a.type_id',
            'c.goods_id as type_id',
        )
            ->from('sell_out_serial_numbers as a')
            ->leftJoin('materiel_type as b', 'b.id', '=', 'a.type_id')
            ->leftJoin('serial_number as c','c.serial_no','=','a.serial_number')
            ->where('sell_id', $data['id'])
            ->where('c.package_id', $data['type_id'])
            ->where('c.status',0)
            ->whereIn('c.goods_id', $productContentTypeId)
            ->distinct()->get()->toArray();

        $arr = [];
        if(!empty($getSellSerialInfo)) {
            foreach($getSellSerialInfo as $value) {
                $arr[$value['type_id']]['type_id'] = $value['type_id'];
                $arr[$value['type_id']]['materiel_name'] = $value['materiel_name'];
                $arr[$value['type_id']]['type_name'] = $value['type_name'];
                $arr[$value['type_id']]['serial_info'][] = [
                    'serial_id' => $value['serial_id'],
                    'serial_no' => $value['serial_number'],
                ];
            }
        }

        //检查有无关联的生产订单
        $getSellProductInfo = ProductOrderModel::where([
            'product_source' => 1,
            'product_source_id' => $data['id'],
            'product_status' => 2
        ])
            ->first();

        if(!empty($getSellProductInfo)) {
            $slaveContentStorageInfo = ProductSlaveContentStorageModel::select(
                'a.serial_id',
                'a.type_id',
                'materiel_name',
                'type_name',
                'serial_no',
                'a.storage_manage_id',
                'b.serial_no',
                'a.serial_id',
            )
                ->where([
                    'product_order_id' => $getSellProductInfo['id'],
                ])
                ->from('product_slave_content_storage as a')
                ->leftJoin('serial_number as b', 'b.id', '=', 'a.serial_id')
                ->leftJoin('materiel_type as c', 'c.id', '=', 'a.type_id')
                ->where('a.serial_id', '!=', 0)
                ->whereRaw('num = storage_operate_num')
                ->whereIn('a.type_id', $productContentTypeId)
                ->get()->toArray();

            if(!empty($slaveContentStorageInfo)) {
                foreach ($slaveContentStorageInfo as $val) {
                    if (isset($arr[$val['type_id']])) {
                        $arr[$val['type_id']]['serial_info'][] = [
                            'serial_id' => $val['serial_id'],
                            'serial_no' => $val['serial_no'],
                            'storage_manage_id' => $val['storage_manage_id']
                        ];
                    } else {
                        $arr[$val['type_id']]['type_id'] = $val['type_id'];
                        $arr[$val['type_id']]['materiel_name'] = $val['materiel_name'];
                        $arr[$val['type_id']]['type_name'] = $val['type_name'];
                        $arr[$val['type_id']]['serial_info'][] = [
                            'serial_id' => $val['serial_id'],
                            'serial_no' => $val['serial_no'],
                            'storage_manage_id' => $val['storage_manage_id']
                        ];
                    }
                }
            }
        }

        return array_values($arr);
    }

    public static function sellSerialList1(array $data)
    {
        //获取所有套件内容
        $contentInfo = MaterielProductContentModel::where('product_id', $data['type_id'])
            ->get()->toArray();

        $productContentTypeId = [];//套件商品id
        foreach($contentInfo as $value) {
            $productContentTypeId[] = $value['type_id'];
        }

        //获取销售单已使用的序列号
        $getSellSerialInfo = SellOutSerialNumbersModel::select(
            'a.serial_number',
            'b.materiel_name',
            'b.type_name',
            'b.materiel_no',
            'b.materiel_name',
            'a.type_id',
            'c.goods_id as type_id'
        )
            ->from('sell_out_serial_numbers as a')
            ->leftJoin('materiel_type as b', 'b.id', '=', 'a.type_id')
            ->leftJoin('serial_number as c','c.serial_no','=','a.serial_number')
            ->where('sell_id', $data['id'])
            ->where('c.package_id', '>',0)
            ->where('c.status',0)
            ->whereIn('c.goods_id', $productContentTypeId)
            ->distinct()->get()->toArray();

            /* ->where('c.package_id', '>',0)
            ->whereIn('c.goods_id', $productContentTypeId)
            ->distinct()->get()->toArray(); */
        $arr = [];
        if(!empty($getSellSerialInfo)) {
            foreach($getSellSerialInfo as $value) {
                $serialInfo = SerialNumberModel::where([
                    'serial_no' => $value['serial_number'],
                    'goods_id' => $value['type_id'],
                ])
                    ->first();

                $arr[$value['type_id']]['type_id'] = $value['type_id'];
                $arr[$value['type_id']]['materiel_name'] = $value['materiel_name'];
                $arr[$value['type_id']]['type_name'] = $value['type_name'];
                $arr[$value['type_id']]['serial_info'][] = [
                    'serial_id' => $serialInfo['id'],
                    'serial_no' => $value['serial_number'],
                ];
            }
        }

        //检查有无关联的生产订单
        $getSellProductInfo = ProductOrderModel::where([
            'product_source' => 1,
            'product_source_id' => $data['id'],
            'product_status' => 2
        ])
            ->first();

        if(!empty($getSellProductInfo)) {
            $slaveContentStorageInfo = ProductSlaveContentStorageModel::select(
                'a.serial_id',
                'a.type_id',
                'materiel_name',
                'type_name',
                'serial_no',
                'a.storage_manage_id'
            )
                ->where([
                    'product_order_id' => $getSellProductInfo['id'],
                ])
                ->from('product_slave_content_storage as a')
                ->leftJoin('serial_number as b', 'b.id', '=', 'a.serial_id')
                ->leftJoin('materiel_type as c', 'c.id', '=', 'a.type_id')
                ->where('a.serial_id', '!=', 0)
                ->whereRaw('num = storage_operate_num')
                ->whereIn('a.type_id', $productContentTypeId)
                ->get()->toArray();

            if(!empty($slaveContentStorageInfo)) {
                foreach($slaveContentStorageInfo as $val) {
                    if(isset($arr[$val['type_id']])) {
                        $arr[$val['type_id']]['serial_info'][] = [
                            'serial_id' => $val['serial_id'],
                            'serial_no' => $val['serial_no'],
                            'storage_manage_id' => $val['storage_manage_id']
                        ];
                    }
                    else {
                        $arr[$val['type_id']]['type_id'] = $val['type_id'];
                        $arr[$val['type_id']]['materiel_name'] = $val['materiel_name'];
                        $arr[$val['type_id']]['type_name'] = $val['type_name'];
                        $arr[$val['type_id']]['serial_info'][] = [
                            'serial_id' => $val['serial_id'],
                            'serial_no' => $val['serial_no'],
                            'storage_manage_id' => $val['storage_manage_id']
                        ];
                    }
                }
            }
        }

        foreach($arr as &$vv) {
            foreach($contentInfo as $vv1) {
                if($vv['type_id'] == $vv1['type_id']) {
                    $vv['num'] = $vv1['num'];
                }
            }
        }

        return array_values($arr);
    }

    public static function sellOut(int $int, $id, $status, $goodsInfo = '', $package = '', array $data, $isUseShelf)
    {
        DB::beginTransaction();
        try {
            //更新销售单状态
            SellModel::where('id', $id)
                ->update(['out_status'=>1]);
            if(!empty($goodsInfo)) {
                $goodsInfo = json_decode($goodsInfo,true);
                $serialData = [];//将被出库的序列号
                $sellOutSerialData = [];//增加销售单出库序列号记录
                $insertSellOut = [];//新增销售单商品出库记录
                $updateSellOut = [];//更新销售单商品出库数量
                $sellGoodsDetailData = [];//更新销售单中商品已出库数量

                $prepareOutData['all_id'] = $id;
                $prepareOutData['remark'] = !empty($data['remark'])?$data['remark']:'';
                $prepareOutData['all_id_type'] = 2;
                $prepareOutData['out_storage_time'] = $data['in_storage_time'];

                foreach($goodsInfo as $value) {
                    $storageInfo = StorageModel::where('id', $value['warehouse_id'])->first();
                    //查询商品信息
                    $materielTypeInfo = MaterielsTypeModel::where('id', $value['materiel_type_id'])->first();

                    $sellGoodsDetailInfo = SellGoodsDetailModel::where([
                        'sell_id' => $data['id'],
                        'materiel_type_id' => $value['materiel_type_id'],
                        'warehouse_id'=>$value['warehouse_id']
                    ])
                        ->first();

                    $leftNum = $sellGoodsDetailInfo['num'] - $sellGoodsDetailInfo['out_num'];//可操作出库数量
                    if($value['num'] > $leftNum) {
                        throw new Exception('商品:'.$sellGoodsDetailInfo['materiel_name'].'-'.
                            $sellGoodsDetailInfo['type_name'].'可操作数量不足，当前可操作数量为：'.$leftNum
                        );
                    }

                    $allSerialNo = '';
                    if(isset($value['serial_no'])) {
                        $allSerialNoArr = array_filter(explode(',', $value['serial_no']), function($v) {
                            return $v !== '';
                        });

                        $getAllSerialInfo = SerialNumberModel::whereIn('id', $allSerialNoArr)->get()->toArray();

                        foreach($getAllSerialInfo as $vv1) {
                            $allSerialNo .= $vv1['serial_no'].',';
                        }

                        $allSerialNo = substr($allSerialNo, 0, -1);
                    }

                    $prepareOutData['content'][] = [
                        'type_id' => $value['materiel_type_id'],
                        'num' => $value['num'],
                        'name' => $materielTypeInfo['materiel_name'],
                        'type_name' => $materielTypeInfo['type_name'],
                        'price' => $value['price'],
                        'warehouse' => $storageInfo['storage_name'],
                        'warehouse_id' => $storageInfo['id'],
                        'serial_no' => $allSerialNo,
                        'shelf_id' => $value['shelf_id'],
                        'location_id' => $value['location_id'],
                    ];

                    $sellGoodsDetailData[] = [
                        'id' => $sellGoodsDetailInfo['id'],
                        'out_num' => $sellGoodsDetailInfo['out_num'] + $value['num'],
                    ];

                    //销售单商品出库记录
                    $sellOutStorageInfo = SellOutStorageModel::where([
                        'materiel_type_id' => $value['materiel_type_id'],
                        'sell_id' => $id,
                        'shelf_id' => $value['shelf_id'],
                        'location_id' => $value['location_id'],
                    ])->first();

                    //销售单出库信息记录
                    if(empty($sellOutStorageInfo)) {
                        $insertSellOut[] = [
                            'materiel_type_id' => $sellGoodsDetailInfo['materiel_type_id'],
                            'name' => $materielTypeInfo['materiel_name'],
                            'type_name' => $materielTypeInfo['type_name'],
                            'num' => $value['num'],
                            'sell_id' => $data['id'],
                            'price' => $value['price'],
                            'warehouse_id' => $storageInfo['id'],
                            'warehouse' => $storageInfo['storage_name'],
                            'remark' => $value['remark'],
                            'shelf_id' => $value['shelf_id'],
                            'location_id' => $value['location_id'],
                        ];
                    }
                    else {
                        $updateSellOut[] = [
                            'id' => $sellOutStorageInfo['id'],
                            'num' => $sellOutStorageInfo['num'] + $value['num'],
                            'remark' => $value['remark']
                        ];
                    }

                    if($value['is_use_serial']) {//是否使用序列号
                        if(empty($value['serial_no'])) {
                            throw new Exception('商品已开启序列号，请选择序列号后重试');
                        }

                        $serialNoArr = array_filter(explode(',', $value['serial_no']), function($v) {
                            return $v !== '';
                        });

                        //检查是否存在亦使用的序列号
                        $checkSerial = SerialNumberModel::where('main_id', $data['main_id'])
                            ->where('status', 0)
                            ->whereIn('id', $serialNoArr)->first();

                        if(!empty($checkSerial)) {
                            throw new Exception('序列号:'.$checkSerial['serial_no'].'已使用，请重新选择');
                        }

                        //检查序列号是否重复使用
                        foreach($serialNoArr as $serialValue) {
                            $getSerialInfo = SerialNumberModel::where('id', $serialValue)->first();
                            if(in_array($serialValue, $serialData)) {
                                throw new Exception('序列号:'.$getSerialInfo['serial_no'].'已被使用，请重新选择');
                            }

                            if($materielTypeInfo['is_product_materiel']) {
                                $serialData[] = [
                                    'id' => $getSerialInfo['id'],
                                    'package_id' => $value['materiel_type_id'],
                                    'sell_id' => $data['id'],
                                    'status' => 0
                                ];
                            }
                            else {
                                $serialData[] = [
                                    'id' => $getSerialInfo['id'],
                                    'sell_id' => $data['id'],
                                    'status' => 0,
                                    'package_id' => 0
                                ];
                            }

                            $sellOutSerialData[] = [
                                'main_id' =>  $data['main_id'],
                                'created_at' => time(),
                                'sell_id' => $data['id'],
                                'type_id' => $value['materiel_type_id'],
                                'serial_number' => $getSerialInfo['serial_no'],
                                'serial_id' => $serialValue,
                                'status' => 1
                            ];
                        }
                    }
                }

                //记录销售单序列号使用情况
                if(!empty($sellOutSerialData)) {
                    SellOutSerialNumbersModel::insert($sellOutSerialData);
                }

                //序列号更变为已使用
                if(!empty($serialData)) {
                    batch()->update(new SerialNumberModel, $serialData, 'id');
//                    SerialNumberModel::whereIn('id', $serialData)->update(['status' => 0]);
                }

                if(!empty($updateSellOut)) {
                    batch()->update(new SellOutStorageModel, $updateSellOut, 'id');
                }

                if(!empty($insertSellOut)) {
                    SellOutStorageModel::insert($insertSellOut);
                }

                if(!empty($sellGoodsDetailData)) {
                    batch()->update(new SellGoodsDetailModel, $sellGoodsDetailData, 'id');
                }

                if(isset($prepareOutData['content'])) {
                    $res = StorageManageService::outStorage1($data['user_id'], $data['main_id'], $prepareOutData, $id, $isUseShelf);
                    if($res['code']){
                        throw new Exception($res['msg']);
                    }
                }
            }

            if(!empty($package)) {
                $sellInfo = SellModel::where('id', $id)->first();
                $packageInfo = json_decode($package,true);
                $sellGoodsList = [];
                foreach($packageInfo as $value) {
                    $SellPackageDetailInfo = SellPackageDetailModel::select(
                        'a.*',
                        'b.package_name'
                    )
                        ->from('sell_package_detail as a')
                        ->leftJoin('package as b', 'b.id', '=', 'a.package_id')
                        ->where([
                            'sell_id' => $data['id'],
                            'a.package_id' => $value['package_id'],
                            'a.main_id' => $data['main_id'],
                        ])->first()->toArray();

                    if (empty($SellPackageDetailInfo)) {
                        return [
                            'code' => 1,
                            'msg' => '销售单内指定的套餐不存在，无法出库',
                            'data' => ''
                        ];
                    }

                    if ($value['num'] > ($SellPackageDetailInfo['num'] - $SellPackageDetailInfo['out_num'])) {
                        return [
                            'code' => 1,
                            'msg' => '套餐可出库数量不足',
                            'data' => ''
                        ];
                    }
                    $logpackageNewId = LogPackageModel::insertGetId([
                        'package_id' => $value['package_id'],
                        'package_name' => $SellPackageDetailInfo['package_name'],
                        'num' => $SellPackageDetailInfo['num'],
                        'sell_price' => $value['price'],
                        'cost' => sprintf('%.6f', self::getPackageCost($id, $value['package_id']) * $SellPackageDetailInfo['num']),
                        'out_storage_time' => strtotime($data['in_storage_time']),
                        'all_id_type' => 2,
                        'all_id' => $id,
                        'user_id' => $data['user_id'],
                        'main_id' => $data['main_id'],
                        'remark' => empty($value['remark'])?'':$value['remark'],
                        'created_at' => time(),
                    ]);

                    $sellOutStoragePackage = SellOutStoragePackageModel::where([
                        'package_id' => $value['package_id'],
                        'sell_id' => $id
                    ])->first();

                    if (empty($sellOutStoragePackage)) {
                        $sellOutStoragePackageId = SellOutStoragePackageModel::insertGetId([
                            'package_id' => $value['package_id'],
                            'price' => $SellPackageDetailInfo['price'],
                            'num' => $value['num'],
                            'remark' => empty($value['remark'])?'':$value['remark'],
                            'sell_id' => $id
                        ]);

                    } else {
                        $sellOutStoragePackageId = $sellOutStoragePackage['id'];

                        SellOutStoragePackageModel::where('id', $sellOutStoragePackage['id'])
                            ->increment('num', $value['num']);
                    }

                    $package_content_arr = $value['package_content'];

                    foreach ($package_content_arr as $content){

                        $storageManageInfo = StorageManageModel::select('a.*','materiel_type_id')
                            ->from('storage_manage as a')
                            ->leftJoin('sell_package_content as b','b.storage_manage_id','=','a.id')
                            ->where('b.id',$content['package_content_id'])->first();

                        $minfo = MaterielsTypeModel::select('is_use_serial')->where('id',$storageManageInfo['materiel_type_id'])->first();

                        if($minfo['is_use_serial'] == 1){
                            $serial_no_array = explode(',',$content['serial_no']);

                            if(empty($serial_no_array)){
                                throw new \Exception('序列号不能为空');
                            }

                            if(count($serial_no_array) != $value['num']*$content['num']){
                                throw new \Exception('序列号个数与入库数量不符');
                            }
                            foreach ($serial_no_array as $serial_key => $serial_data){
                                //检查序列号是否使用
                                $number_info = SerialNumberModel::where(['goods_id' => $storageManageInfo['materiel_type_id'],'serial_no' => $serial_data,'status' => SerialNumberModel::UNUSEDSTATUS])->first();

                                if(!$number_info){
                                    throw new \Exception('该商品：'.$value['materiel_type_id'].'的序列号：'.$serial_data.'已被使用');
                                }

                                $id = SellPackageSerialNumberModel::insert([

                                    'main_id' =>  $data['main_id'],
                                    'created_at' => time(),
                                    'sell_id' => $data['id'],
                                    'type_id' => $number_info['goods_id'],
                                    'sell_package_content_id' => $content['package_content_id'],
                                    'serial_number' => $serial_data,
                                    'status' => 1
                                ]);

                                SerialNumberModel::where(['serial_no' => $serial_data,'status' => SerialNumberModel::UNUSEDSTATUS,
                                    'goods_id' => $number_info['goods_id'],
                                ])->update(['status' => SerialNumberModel::USEDSTATUS]);
                            }
                        }


                        //查询库存信息
                        /*  $storageManageInfo = StorageManageModel:: where(['id' => $number_info['storage_manage_id'],'delete_flag' =>0])->first(); */

                        if (empty($storageManageInfo)) {
                            return [
                                'code' => 1,
                                'msg' => '套餐内商品无库存信息，无法完成出库',
                                'data' => ''
                            ];
                        }

                        if($storageManageInfo['in_storage_num'] < ($value['num'] * $content['num'])) {
                            return [
                                'code' => 1,
                                'msg' => '套餐内商品库存数不足，无法完成出库',
                                'data' => ''
                            ];
                        }

                        StorageManageModel::where('id', $storageManageInfo['id'])
                            ->decrement('in_storage_num', $value['num']*$content['num']);

                        $prepareInfo = SellPackagePrepareOutLogModel::where('sell_id', $id)
                            ->where('package_id', $value['package_id'])->first();

                        if(empty($prepareInfo)) {
                            StorageManageModel::where('id', $storageManageInfo['id'])
                                ->decrement('virtual_storage_num', $value['num'] * $content['num']);
                        }

                        LogPackageContentModel::insert([
                            'log_package_id' => $logpackageNewId,
                            'package_id' => $value['package_id'],
                            'storage_id' => $storageManageInfo['id'],
                            'storage_name' => $storageManageInfo['storage_name'],
                            'storage_address' => $storageManageInfo['storage_address'],
                            'materiel_class_id' => $storageManageInfo['materiel_class_id'],
                            'materiel_class_name' => $storageManageInfo['materiel_class_name'],
                            'materiel_class_no' => $storageManageInfo['materiel_class_no'],
                            'materiel_type_id' => $storageManageInfo['type_id'],
                            'materiel_name' => $storageManageInfo['materiel_name'],
                            'type_name' => $storageManageInfo['type_name'],
                            'materiel_no' => $storageManageInfo['materiel_no'],
                            'operate_num' => $value['num'] * $content['num'],
                            'out_storage_manage_id' => $storageManageInfo['id'],
                            'last_storage_num' => $storageManageInfo['in_storage_num'],
                            'next_storage_num' => $storageManageInfo['in_storage_num'] - ($value['num'] * $content['num']),
                            'all_id_type' => 4,
                            'all_id' => $id,
                            'user_id' => $data['user_id'],
                            'main_id' => $data['main_id'],
                            'created_at' => time(),

                            'shelf_id' =>$storageManageInfo['shelf_id'],
                            'location_id' =>$storageManageInfo['location_id'],

                        ]);

                        $sellGoodsList[] = [
                            'materiel_type_id' => $storageManageInfo['type_id'],
                            'cost_price' => $storageManageInfo['materiel_mean_cost'],
                            'num' => $value['num'] * $content['num'],
                            'main_id' => $data['main_id'],
                            'user_id' => $data['user_id'],
                            'sell_id' => $id,
                            'sell_date' => strtotime($sellInfo['sell_date']),
                            'created_at' => time(),
                        ];

                        $sellOutStoragePackageContent = SellOutStoragePackageContentModel::where([
                            'o_s_package_id' => $sellOutStoragePackageId,
                            'type_id' => $storageManageInfo['type_id'],
                            'storage_id' => $storageManageInfo['storage_id'],
                            'shelf_id' => $storageManageInfo['shelf_id'],
                            'location_id' => $storageManageInfo['location_id'],
                        ])->first();
                        if (empty($sellOutStoragePackageContent)) {
                            SellOutStoragePackageContentModel::insert([
                                'type_id' => $storageManageInfo['type_id'],
                                'storage_id' => $storageManageInfo['storage_id'],
                                'package_content_id' => $content['package_content_id'],
                                'storage_manage_id' => $storageManageInfo['id'],
                                'o_s_package_id' => $sellOutStoragePackageId,
                                'sell_id' => $id,
                                'num' => $value['num'] * $content['num'],
                                'user_id' => $data['user_id'],
                                'main_id' => $data['main_id'],
                                'created_at' => time(),

                                'shelf_id' => $storageManageInfo['shelf_id'],
                                'location_id' => $storageManageInfo['location_id'],

                            ]);
                        } else {
                            SellOutStoragePackageContentModel::where('id', $sellOutStoragePackageContent['id'])
                                ->increment('num', $value['num'] * $storageManageInfo['num']);
                        }
                    }

                    SellPackageDetailModel::where('sell_id', $id)
                        ->where('package_id', $value['package_id'])
                        ->increment('out_num', $value['num']);
                }

                SellGoodsListModel::insert($sellGoodsList);
            }

            $checkSellGoodsInfo = SellGoodsDetailModel::where('sell_id', $id)
                ->whereRaw('num > out_num')->first();

            $status = 1;//1:部分出库;2:全部出库;
            if(empty($checkSellGoodsInfo)) {
                $status = 2;
            }

            $checkSellPackageDetailInfo = SellPackageDetailModel::where('sell_id', $id)
                ->whereRaw('num > out_num')->first();

            if(empty($checkSellGoodsInfo)) {
                $status = 2;
            }
            else {
                $status = 1;
            }

            SellModel::where('id', $id)->update(['out_status' => $status]);

            if($status == 1) {
                CheckModel::where(['main_id'=>$data['main_id'],'type'=>2,'all_id'=>$id])
                    ->update(['out_in_status'=>1]);

                ProductOrderModel::where([
                    'product_source' => 1,
                    'product_source_id' => $id
                ])
                    ->update(['product_status' => 1]);
            }
            else {
                SellModel::where('id',$id)->update(['out_status'=>2,'prepare_out_status' => 0]);//全部完成更新状态
                CheckModel::where(['main_id'=>$data['main_id'],'type'=>2,'all_id'=>$id])
                    ->update(['status'=>1,'out_in_status'=>0]);
                ProductOrderModel::where([
                    'product_source' => 1,
                    'product_source_id' => $id
                ])
                    ->update(['product_status' => 2]);
            }

            DB::commit();
            return ['code' => 0, 'msg' => 'success', 'data' => ''];
        }
        catch(Exception $e) {
            DB::rollBack();
            Log::debug('销售单出库异常:'.var_export($e->getMessage(),true));
            return ['code' => 1, 'msg' => $e->getMessage(), 'data' => ''];
        }
    }

    static private function getSellPackageCost($packageId)
    {
        $packageTotalCost = SellPackageContentModel::select(
            'a.total_num',
            'b.materiel_mean_cost'
        )
            ->from('sell_package_content as a')
            ->leftJoin('storage_manage as b', 'b.id', '=', 'a.storage_manage_id')
            ->where('a.package_id', $packageId)
            ->where('b.delete_flag', 0)
            ->first();

        return $packageTotalCost['total_num'] * $packageTotalCost['materiel_mean_cost'];
    }

    static public function prepare($data)
    {
        DB::beginTransaction();

        try {
            $sellInfo = SellModel::where('id', $data['id'])->first();

            if($sellInfo['prepare_out_status']) {
                return ['code' => 1, 'msg' => '当前销售单已经预出库，无法重复操作', 'data' => ''];
            }

            if($sellInfo['out_status'] != 0) {
                return ['code' => 1, 'msg' => '该销售单已经出库，无法进行预出库操作', 'data' => ''];
            }

            $materielOutInfo = [];
            if(!empty($data['goods_info'])) {
                $goodsInfo = json_decode($data['goods_info'], true);
                $sellGoodsDetailPrepareOutArr = [];

                foreach($goodsInfo as $key => $value) {
                    $sellGoodsDetailInfo = SellGoodsDetailModel::select(
                        'num',
                        'b.id as  materiel_type_id',
                        'b.materiel_name',
                        'b.type_name',
                        'c.id as storage_id',
                        'c.storage_name',
                        'a.shelf_id',
                        'a.location_id',
                    )
                        ->from('sell_goods_detail as a')
                        ->leftJoin('materiel_type as b', 'b.id', '=', 'a.materiel_type_id')
                        ->leftJoin('storage as c', 'c.id', '=', 'a.warehouse_id')
                        ->where('a.id', $value['sell_goods_id'])
                        ->first();

                    $sellGoodsDetailPrepareOutArr[$key] = [
                        'materiel_type_id' => $sellGoodsDetailInfo['materiel_type_id'],
                        'materiel_name' => $sellGoodsDetailInfo['materiel_name'],
                        'type_name' => $sellGoodsDetailInfo['type_name'],
                        'storage_id' => $sellGoodsDetailInfo['storage_id'],
                        'storage_name' => $sellGoodsDetailInfo['storage_name'],
                        'storage_manage_id' => $value['storage_manage_id'],
                        'num' => $sellGoodsDetailInfo['num'],
                        'sell_id' => $data['id'],
                        'shelf_id' => $sellGoodsDetailInfo['shelf_id'],
                        'location_id' => $sellGoodsDetailInfo['location_id'],

                    ];

                    $materielOutInfo[] = [
                        'storage_manage_id' => $value['storage_manage_id'],
                        'num' => $sellGoodsDetailInfo['num']
                    ];
                }

                foreach($materielOutInfo as $vv) {
                    $storageManageInfo = StorageManageModel::where('id', $vv['storage_manage_id'])->first();
                    if($vv['num'] > $storageManageInfo['virtual_storage_num']) {
                        throw new Exception('可用库存数不足，无法完成预出库');
                    }

                    StorageManageModel::where('id', $vv['storage_manage_id'])
                        ->decrement('virtual_storage_num', $vv['num']);
                }

                SellMaterielPrepareOutLogModel::insert($sellGoodsDetailPrepareOutArr);
            }

            $sellPackageContentPrepareOutArr = [];
            if(!empty($data['package_info'])) {
                $packageOutInfo = [];
                $packageInfo = json_decode($data['package_info'], true);

                foreach($packageInfo as $kk => $val) {
                    $sellPackageInfo = SellPackageDetailModel::where('id', $val['sell_package_id'])
                        ->first();

                    $sellPackageContentInfo = SellPackageContentModel::where('package_detail_id', $val['sell_package_id'])
                        ->get()->toArray();


                    $id = SellPackagePrepareOutLogModel::insertGetId([
                        'sell_id' => $data['id'],
                        'package_id' => $sellPackageInfo['package_id'],
                        'num' => $sellPackageInfo['num'],
                        'created_at' => time()
                    ]);

                    foreach($sellPackageContentInfo as $k => $v) {
                        $sellPackageContentPrepareOutArr[] = [
                            'parent_id' => $id,
                            'type_id' => $v['materiel_type_id'],
                            'storage_manage_id' => $v['storage_manage_id'],
                            'sell_id' => $data['id'],
                            'num' => $v['num'],
                            'total_num' => $v['num'] * $sellPackageInfo['num'],
                            'created_at' => time(),

                            'shelf_id' => $v['shelf_id'],
                            'location_id' => $v['location_id'],
                        ];

                        $packageOutInfo[] = [
                            'storage_manage_id' => $v['storage_manage_id'],
                            'num' => $v['num'] *  $sellPackageInfo['num']
                        ];
                    }
                }

                foreach($packageOutInfo as $vv1) {
                    $storageManageInfo = StorageManageModel::where('id', $vv1['storage_manage_id'])->first();

                    if($vv1['num'] > $storageManageInfo['virtual_storage_num']) {
                        throw new Exception('可用库存数不足，无法完成预出库');
                    }

                    StorageManageModel::where('id', $vv1['storage_manage_id'])
                        ->decrement('virtual_storage_num', $vv1['num']);
                }

                SellPackageContentPrepareOutLogModel::insert($sellPackageContentPrepareOutArr);
            }

            SellModel::where('id', $data['id'])->update(['prepare_out_status' => 1]);
            DB::commit();
            return ['code' => 0, 'msg' => 'success', 'data' => ''];
        }
        catch (Exception $e) {
            DB::rollBack();
            Log::debug('销售单预出库'.var_export($e->getMessage(), true));
            return ['code' => 1, 'msg' => $e->getMessage(), 'data' => ''];
        }
    }

    static public function payHistory($id)
    {
        if(empty(SellPayRecordModel::where('sell_id', $id)->first())) {
            return '';
        }
        else {
            return SellModel::select(
                'order_no',
                'expend',
                'collection_time',
                'collection_account',
                'a.main_id',
            )
                ->from('sell as a')
                ->leftJoin('sell_pay_record as b', 'a.id', '=', 'b.sell_id')
                ->where('a.id', $id)
                ->get()->toArray();

//            return SellModel::select(
//                'a.order_no',
//                'b.*'
//            )
//                ->from('sell as a')
//                ->leftJoin('sell_pay_record as b', 'a.id', '=', 'b.sell_id')
//                ->where('a.id', $id)
//                ->get()->toArray();
        }
    }

    /**
     * 使用批次号出库
     * created at 在 2022/06/20 13:56 by SunWu
     * @param $id   主键id
     * @param $status 入库状态：1-部分 2-全部
     * @param $goods  商品信息 obj
     */
    static public function outWithBatch($id,$status,$goods='',$package='',$data, $isUseShelf = 0)
    {
        $paramsArr = [];//出入库参数
        $paramsArr['all_id'] = $id;
        isset($data['remark'])?$paramsArr['remark'] = $data['remark']:$paramsArr['remark'] = '';
        $paramsArr['all_id_type'] = 2;//销售退货均为2
        $paramsArr['out_storage_time'] = $data['in_storage_time'];

        $sellInfo = SellModel::where('id', $id)->first();

        if($sellInfo['out_status'] == 2) {
            return ['code' => 1, 'msg' => '销售单已完成出库，请勿重复操作'];
        }

        $result = self::partSell($paramsArr, $id, $goods, $package, $data, $isUseShelf);
//        //status:0-部分 1-全部
//        switch($status) {
//            case 0:
//                $result = self::partSell($paramsArr, $id, $goods, $package, $data);
//                break;
//            case 1:
//                $result = self::allSell($id, $data);
//                break;
//        }

        return $result;
    }

    static private function allSell($id, $data)
    {
        $sellGoodsInfo = SellGoodsDetailModel::select(
            'id',
            'materiel_type_id',
            'price',
            'cost_price',
            DB::raw('(num - out_num) as rest_num'),
            'warehouse_id'
        )
            ->with('goodsBatchInfo', function($query) {
                $query->where('rest_num', '>', 0)->with('storageBatchInfo', function($query) {
                    $query->where('batch_left_num', '>', '0')->with('storageManageInfo', function($query) {
                        $query->select(
                            'storage_manage.id',
                            'in_storage_num',
                            'type_id',
                            'a.materiel_name',
                            'a.type_name',
                            'a.materiel_no',
                            'storage_manage.materiel_class_id',
                            'b.class_name',
                            'b.class_no',
                            'storage_id',
                            'c.storage_name',
                            'c.storage_address',
                            'materiel_mean_cost'
                        )
                            ->from('storage_manage')
                            ->leftJoin('materiel_type as a', 'a.id', '=', 'storage_manage.type_id')
                            ->leftJoin('materiel_class as b', 'b.id', '=', 'storage_manage.materiel_class_id')
                            ->leftJoin('storage as c', 'c.id', '=', 'storage_manage.storage_id')
                            ->where('in_storage_num', '>', '0')
                            ->where('storage_manage.delete_flag', 0);
                    });
                });
            })
            ->where('sell_id', $id)
            ->whereRaw('num > out_num')
            ->get()->toArray();

        $sellPackageInfo = SellPackageDetailModel::select(
            'a.*',
            'b.package_name'
        )->with('packageContent', function($query) {
            $query->with('packageBatchInfo', function($query) {
                $query->with('storageBatchInfo', function($query) {
                    $query->with('storageManageInfo', function($query) {
                        $query->select(
                            'storage_manage.id',
                            'in_storage_num',
                            'type_id',
                            'a.materiel_name',
                            'a.type_name',
                            'a.materiel_no',
                            'storage_manage.materiel_class_id',
                            'b.class_name',
                            'b.class_no',
                            'storage_id',
                            'c.storage_name',
                            'c.storage_address',
                            'materiel_mean_cost'
                        )
                            ->from('storage_manage')
                            ->leftJoin('materiel_type as a', 'a.id', '=', 'storage_manage.type_id')
                            ->leftJoin('materiel_class as b', 'b.id', '=', 'storage_manage.materiel_class_id')
                            ->leftJoin('storage as c', 'c.id', '=', 'storage_manage.storage_id')
                            ->where('in_storage_num', '>', '0')
                            ->where('storage_manage.delete_flag', 0);
                    });
                });
            });
        })
            ->from('sell_package_detail as a')
            ->leftJoin('package as b', 'b.id', '=', 'a.package_id')
            ->where('sell_id', $id)
            ->whereRaw('num > out_num')
            ->get()->toArray();

        DB::beginTransaction();

        try {
            SellModel::where('id',$id)->update(['out_status'=>2,'prepare_out_status' => 0]);//全部完成更新状态
            CheckModel::where(['main_id'=>$data['main_id'],'type'=>2,'all_id'=>$id])
                ->update(['status'=>1,'out_in_status'=>0]);

            if(!empty($sellGoodsInfo)) {
                $result = self::allSellMaterielStep1($sellGoodsInfo, $id, $data);

                if(isset($result['code'])) {
                    return $result;
                }
                else {
                    //更新销售单内商品批次可出库数量
                    if(!empty($result['data'])) {
                        foreach($result['data'] as $value) {
                            SellGoodsDetailBatchModel::where('id', $value['id'])
                                ->lockForUpdate()
                                ->decrement('rest_num', $value['num']);
                        }
                    }

                    //更新商品库存批次数量
                    if(empty($result['data1'])) {
                        foreach($result['data1'] as $val) {
                            StorageBatchModel::where('id', $val['id'])
                                ->lockForUpdate()
                                ->decrement('batch_left_num', $val['num']);
                        }
                    }

                    //更新商品库存数量以及虚拟库存数量
                    if(!empty($result['data2'])) {
                        foreach($result['data2'] as $v) {
                            StorageManageModel::where('id', $val['id'])
                                ->lockForUpdate()
                                ->update([
                                    'in_storage_num' => DB::raw("in_storage_num - ".$v['num']),
                                    'virtual_storage_num' => DB::raw("virtual_storage_num - ".$v['num'])
                                ]);
                        }
                    }

                    LogOutStorageModel::insert($result['data3']);
                    LogOutPackageModel::insert($result['data4']);
                    SellOutStorageModel::insert($result['data5']);
                }
            }

            if(!empty($sellPackageInfo)) {
                $restNum = $sellGoodsInfo['num'] - $sellGoodsInfo['out_num'];


            }

            DB::commit();
            return ['code' => 0, 'msg' => 'success', 'data' => ''];
        }
        catch(Exception $e) {
            DB::rollBack();
            Log::debug('销售单全部出库异常'.var_export($e->getMessage(), true));
            return ['code' => 1, 'msg' => '销售单全部出库异常', 'data' => ''];
        }
    }

    //全部出库-套餐
    static private function allSellPackageStep1($sellPackageInfo, $id, $data)
    {
        $logOutPackageInfo = [];
        $decrementPackageDetail = [];
        $decrementPackageBatch = [];
        $decrementStorageBatch = [];
        $decrementStorage = [];
        $prepareOutPackageInfo = [];
        foreach($sellPackageInfo as $value) {
            $decrementPackageDetail[] = [
                'id' => $value['id'],
                'num' => $value['num'] - $value['out_num']
            ];
            foreach($value['package_content'] as $val) {
                $prepareOutPackageInfo[] = [
                    'package_id' => $val['package_id'],
                    'num' => $value['num'] - $value['out_num']
                ];

                $matereilNeedsNum = ($value['num'] - $value['out_num']) * $val['num'];

                $totalNum = 0;
                $totalStorageBatchNum = 0;

                foreach($val['package_batch_info'] as $v) {
                    $totalNum += $v['rest_num'];

                    $decrementPackageBatch[] = [
                        'id' => $v['id'],
                        'num' => $v['rest_num']
                    ];

                    if($v['rest_num'] > $v['storage_batch_info']['batch_left_num']) {
                        return [
                            'code' => 1,
                            'msg' => '批次库存数量不足，无法完成出库',
                            'data' => ''
                        ];
                    }

                    if($matereilNeedsNum > $v['storage_batch_info']['storage_manage_info']['in_storage_num']) {
                        return [
                            'code' => 1,
                            'msg' => '商品库存数不足，无法完成出库',
                            'data' => ''
                        ];
                    }

                    $decrementStorageBatch[] = [
                        'id' => $v['storage_batch_info']['id'],
                        'num' => $matereilNeedsNum,
                    ];
                    $decrementStorage[] = [
                        'id' => $v['storage_batch_info']['storage_manage_info']['id'],
                        'num' => $matereilNeedsNum,
                    ];

                    $logOutPackageInfo[] = [
                        'storage_manage_id' => $v['storage_batch_info']['storage_manage_info']['id'],
                        'materiel_class_id' => $v['storage_batch_info']['storage_manage_info']['materiel_class_id'],
                        'materiel_type_id' => $v['storage_batch_info']['storage_manage_info']['type_id'],
                        'storage_id' => $v['storage_batch_info']['storage_manage_info']['storage_id'],
                        'out_time' => empty($data['in_storage_time'])?time():strtotime($data['in_storage_time']),
                        'mean_cost' => $v['storage_batch_info']['storage_manage_info']['materiel_mean_cost'],
                        'num' => $v['rest_num'],
                        'price' => $value['price'],
                        'all_id_type' => 2,
                        'all_id' => $id,
                        'user_id' => $data['user_id'],
                        'main_id' => $data['main_id'],
                        'created_at' => time()
                    ];

                    $logPackageId = LogPackageModel::insertGetId([
                        'package_id' => $value['package_id'],
                        'package_name' => $value['package_name'],
                        'num' => $value['num'],
                        'all_id_type' => 2,
                        'all_id' => $id,
                        'user_id' => $data['user_id'],
                        'main_id' => $data['main_id'],
                        'remark' => $value['remark'],
                        'created_at' => time(),
                    ]);

                    LogPackageContentModel::insert([
                        'log_package_id' => $logPackageId,
                        'package_id' => $value['package_id'],
                        'storage_id' => $v['storage_batch_info']['storage_manage_info']['storage_id'],
                        'storage_name' => $v['storage_batch_info']['storage_manage_info']['storage_name'],
                        'storage_address' => $v['storage_batch_info']['storage_manage_info']['storage_address'],
                        'materiel_class_id' => $v['storage_batch_info']['storage_manage_info']['materiel_class_id'],
                        'materiel_class_name' => $v['storage_batch_info']['storage_manage_info']['class_name'],
                        'materiel_class_no' => $v['storage_batch_info']['storage_manage_info']['class_no'],
                        'materiel_type_id' => $v['storage_batch_info']['storage_manage_info']['type_id'],
                        'materiel_name' => $v['storage_batch_info']['storage_manage_info']['materiel_name'],
                        'type_name' => $v['storage_batch_info']['storage_manage_info']['type_name'],
                        'operate_num' => $matereilNeedsNum,
                        'out_storage_manage_id' => $v['storage_batch_info']['storage_manage_info']['id'],
                        'storage_batch_id' => $v['storage_batch_info']['id'],
                        'last_storage_num' => $v['storage_batch_info']['storage_manage_info']['in_storage_num'],
                        'next_storage_num' => $v['storage_batch_info']['storage_manage_info']['in_storage_num'] - $matereilNeedsNum,
                        'all_id_type' => 4,
                        'all_id' => $id,
                        'user_id' => $data['user_id'],
                        'main_id' => $data['main_id'],
                        'created_at' => time(),
                    ]);
                }

            }
        }

        return [
            'data' => $logOutPackageInfo,
            'data1' => $decrementPackageDetail,
            'data2' => $decrementPackageBatch,
            'data3' => $decrementStorageBatch,
            'data4' => $decrementStorage,
            'data5' => $prepareOutPackageInfo
        ];
    }

    //全部出库-商品
    static private function allSellMaterielStep1($sellGoodsInfo, $id, $data)
    {
        //需扣除的商品批次库存信息
        $decrementGoodsBatchInfo = [];
        //需扣除的库存商品对应的库存批次信息
        $decrementStorageBatchInfo = [];
        //需扣除的库存信息
        $decrementStorageInfo = [];
        //商品出库记录
        $logOutInfo = [];
        //成本统计
        $logOutPackageInfo = [];
        //销售单商品出库记录
        $sellGoodsOutInfo = [];
        foreach($sellGoodsInfo as $key => $value) {
            if(empty($value['goods_batch_info'])) {
                return ['code' => 1, 'msg' => '当前商品无批次号，请添加后再次尝试', 'data' => ''];
            }

            foreach($value['goods_batch_info'] as $k => $val) {
                $decrementGoodsBatchInfo[$k] = [
                    'id' => $val['id'],
                    'num' => $val['rest_num']
                ];

                if($val['rest_num'] > $val['storage_batch_info']['batch_left_num']) {
                    return [
                        'code' => 1,
                        'msg' => '批次库存数量不足，无法完成出库',
                        'data' => ''
                    ];
                }

                $decrementStorageBatchInfo[$k] = [
                    'id' => $val['storage_batch_info']['id'],
                    'num' => $val['rest_num']
                ];

                if($val['rest_num'] > $val['storage_batch_info']['storage_manage_info']['in_storage_num']) {
                    return [
                        'code' => 1,
                        'msg' => '批次对应的库存数量不足，无法完成出库',
                        'data' => ''
                    ];
                }

                $decrementStorageInfo[$k] = [
                    'id' => $val['storage_batch_info']['storage_manage_info']['id'],
                    'num' => $val['rest_num']
                ];

                $logOutInfo[] = [
                    'storage_batch_id' => $val['storage_batch_info']['id'],
                    'storage_id' => $val['storage_batch_info']['storage_manage_info']['storage_id'],
                    'storage_name' => $val['storage_batch_info']['storage_manage_info']['storage_name'],
                    'storage_address' => $val['storage_batch_info']['storage_manage_info']['storage_address'],
                    'curr_storage_manage_id' => $val['storage_batch_info']['storage_manage_info']['id'],
                    'materiel_class_id' => $val['storage_batch_info']['storage_manage_info']['materiel_class_id'],
                    'materiel_class_name' => $val['storage_batch_info']['storage_manage_info']['class_name'],
                    'materiel_class_no' => $val['storage_batch_info']['storage_manage_info']['class_no'],
                    'materiel_type_id' => $val['storage_batch_info']['storage_manage_info']['type_id'],
                    'materiel_name' => $val['storage_batch_info']['storage_manage_info']['materiel_name'],
                    'type_name' => $val['storage_batch_info']['storage_manage_info']['type_name'],
                    'materiel_no' => $val['storage_batch_info']['storage_manage_info']['materiel_no'],
                    'operate_num' => $val['rest_num'],
                    'last_storage_num' => $val['storage_batch_info']['storage_manage_info']['in_storage_num'],
                    'next_storage_num' => $val['storage_batch_info']['storage_manage_info']['in_storage_num'] - $val['rest_num'],
                    'materiel_mean_cost' => $val['storage_batch_info']['storage_manage_info']['materiel_mean_cost'],
                    'all_id_type' => 2,
                    'all_id' => $id,
                    'user_id' => $data['user_id'],
                    'main_id' => $data['main_id'],
                    'remark' => empty($data['remark'])?'':$data['remark'],
                    'out_storage_time' => empty($data['in_storage_time'])?time():strtotime($data['in_storage_time']),
                    'created_at' => time()
                ];

                $sellGoodsOutInfo[] = [
                    'materiel_type_id' => $val['storage_batch_info']['storage_manage_info']['type_id'],
                    'name' => $val['storage_batch_info']['storage_manage_info']['materiel_name'],
                    'type_name' => $val['storage_batch_info']['storage_manage_info']['type_name'],
                    'num' => $val['rest_num'],
                    'sell_id' => $id,
                    'price' => $value['price'],
                    'warehouse' => $val['storage_batch_info']['storage_manage_info']['storage_name'],
                    'warehouse_id' => $val['storage_batch_info']['storage_manage_info']['storage_id'],
                ];

                $logOutPackageInfo[] = [
                    'storage_manage_id' => $val['storage_batch_info']['storage_manage_info']['id'],
                    'materiel_class_id' => $val['storage_batch_info']['storage_manage_info']['materiel_class_id'],
                    'materiel_type_id' => $val['storage_batch_info']['storage_manage_info']['type_id'],
                    'storage_id' => $val['storage_batch_info']['storage_manage_info']['storage_id'],
                    'out_time' => empty($data['in_storage_time'])?time():strtotime($data['in_storage_time']),
                    'mean_cost' => $val['storage_batch_info']['storage_manage_info']['materiel_mean_cost'],
                    'num' => $val['rest_num'],
                    'price' => $value['price'],
                    'all_id_type' => 2,
                    'all_id' => $id,
                    'user_id' => $data['user_id'],
                    'main_id' => $data['main_id'],
                    'created_at' => time()
                ];
            }
        }

        return [
            'data' => $decrementGoodsBatchInfo,
            'data1' => $decrementStorageBatchInfo,
            'data2' => $decrementStorageInfo,
            'data3' => $logOutInfo,
            'data4' => $logOutPackageInfo,
            'data5' => $sellGoodsOutInfo
        ];
    }

    //部分出库
    static private function partSell($paramsArr, $id, $goods, $package, $data, $isUseShelf)
    {
        DB::beginTransaction();

        try {
            //更新销售入库状态
            SellModel::where('id',$id)->update(['out_status'=>1, 'prepare_out_status' => 0]);

            $goods = json_decode($goods, true);
            $package = json_decode($package, true);

            if(empty($goods) && empty($package)){
                return ['code' => 1, 'msg' => '销售出库异常！', 'data' => ''];
            }

            if(!empty($goods) || !empty($package)) {
                if(!empty($goods)) {
                    $materielOutResult = self::selMaterielPartStep1($id, $goods, $data, $isUseShelf);

                    if($materielOutResult['code'] != 0) {
                        return $materielOutResult;
                    }
                }

                if(!empty($package)) {
                    self::sellPackagePart($id, $package, $data, $isUseShelf);
                }
            }

            $sellGoodsInfo = SellGoodsDetailModel::where('sell_id', $id)
                ->whereRaw('num > out_num')
                ->first();

            $sellPackageInfo = SellPackageDetailModel::where('sell_id', $id)
                ->whereRaw('num > out_num')
                ->first();

            if(empty($sellGoodsInfo) && empty($sellPackageInfo)) {
                SellModel::where('id',$id)->update(['out_status'=>2,'prepare_out_status' => 0]);//全部完成更新状态
                CheckModel::where(['main_id'=>$data['main_id'],'type'=>2,'all_id'=>$id])
                    ->update(['status'=>1,'out_in_status'=>0]);
            }
            else {
                CheckModel::where(['main_id'=>$data['main_id'],'type'=>2,'all_id'=>$id])
                    ->update(['out_in_status'=>1]);
            }

            DB::commit();
            return ['code' => 0, 'msg' => 'success', 'data' => ''];
        }
        catch(Exception $e) {
            DB::rollBack();
            Log::debug('销售单部分出库异常'.var_export($e->getMessage(), true));
            return ['code' => 1, 'msg' => $e->getMessage(), 'data' => ''];
        }
    }

    static private function sellPackagePart($id, $package, $data)
    {
        $outNum = 0;
        $sellGoodsList = [];

        $sellInfo = SellModel::where('id', $id)->first();

        foreach($package as $value) {
            //销售单套餐信息
            $packageDetailInfo = SellPackageDetailModel::select(
                'a.id',
                'b.package_name',
                'num',
                'out_num',
                'price'
            )
                ->from('sell_package_detail as a')
                ->leftJoin('package as b', 'b.id', '=', 'a.package_id')
                ->where([
                    'package_id' => $value['package_id'],
                    'sell_id' => $id
                ])
                ->whereRaw('num > out_num')
                ->first();

            if (empty($packageDetailInfo)) {
                throw new Exception('套餐已全部出库，无法重复操作');
            }

            if (($packageDetailInfo['num'] - $packageDetailInfo['out_num']) < $value['num']) {
                throw new Exception('套餐:' . $packageDetailInfo['package_name'] . '可出库数量不足，当前剩余:' . ($packageDetailInfo['num'] - $packageDetailInfo['out_num']));
            }

            SellPackageDetailModel::where([
                'id' => $packageDetailInfo['id'],
                'sell_id' => $id
            ])
                ->increment('out_num', $value['num']);

            $logPackageId = LogPackageModel::insertGetId([
                'package_id' => $value['package_id'],
                'package_name' => $packageDetailInfo['package_name'],
                'num' => $value['num'],
                'sell_price' => $value['price'],
                'cost' => sprintf('%.6f', OutInRepealService::getPackageCost($id, $value['package_id']) * $value['num']),
                'out_storage_time' => strtotime($data['in_storage_time']),
                'all_id_type' => 2,
                'all_id' => $id,
                'user_id' => $data['user_id'],
                'main_id' => $data['main_id'],
                'remark' => empty($value['remark']) ? '' : $value['remark'],
                'created_at' => time()
            ]);

            foreach ($value['package_content'] as $val) {
                $packageContentInfo = SellPackageContentModel::select(
                    'a.id',
                    'b.id as materiel_type_id',
                    'num',
                    'materiel_name',
                    'type_name',
                    'rest_num'
                )
                    ->from('sell_package_content as a')
                    ->leftJoin('materiel_type as b', 'b.id', '=', 'a.materiel_type_id')
                    ->where('a.id', $val['package_content_id'])->first();

                    //查询商品信息
                    $minfo = MaterielsTypeModel::select('is_use_serial')->where('id', $packageContentInfo['materiel_type_id'])->first();

                    if($minfo['is_use_serial'] == 1 && !empty($val['serial_no'])){

                        $serial_no_array = explode(',',$val['serial_no']);

                        if(empty($serial_no_array)){
                            throw new Exception('序列号不能为空');
                        }

                        if(count($serial_no_array) != $val['num']){
                            throw new Exception('序列号个数与入库数量不符');
                        }
                        foreach ($serial_no_array as $k => $serial_data){

                            //检查序列号是否使用
                            $number_info = SerialNumberModel::where(['goods_id' => $packageContentInfo['materiel_type_id'],'serial_no' => $serial_data,'status' => SerialNumberModel::UNUSEDSTATUS])->first();

                            if(empty($number_info)){

                                throw new Exception('该商品：'.$packageContentInfo['materiel_type_id'].'的序列号：'.$serial_data.'不存在');
                            }

                            SellPackageSerialNumberModel::insert([

                                'main_id' =>  $data['main_id'],
                                'created_at' => time(),
                                'sell_id' => $data['id'],
                                'type_id' => $number_info['goods_id'],
                                'serial_number' => $serial_data,
                                'sell_package_content_id' => $packageContentInfo['id'],
                                'status' => 1
                            ]);

                            SerialNumberModel::where(['serial_no' => $serial_data,'status' => SerialNumberModel::UNUSEDSTATUS,
                                'goods_id' => $number_info['goods_id'],
                            ])->update(['status' => SerialNumberModel::USEDSTATUS]);

                            $storageBatchInfo = SerialNumberModel::select(
                                'a.id',
                                'b.id as storage_manage_id',
                                'b.storage_id',
                                'c.storage_name',
                                'c.storage_address',
                                'b.type_id as materiel_type_id',
                                'd.materiel_name',
                                'd.type_name',
                                'd.materiel_no',
                                'b.materiel_class_id',
                                'e.class_name',
                                'e.class_no',
                                'in_storage_num',
                                'alert_num',
                                'g.id as sell_package_content_id'
                                )
                                ->from('serial_number as a')
                                ->leftJoin('storage_manage as b', 'b.id', '=', 'a.storage_manage_id')
                                ->leftJoin('storage as c', 'c.id', '=', 'b.storage_id')
                                ->leftJoin('materiel_type as d', 'd.id', '=', 'b.type_id')
                                ->leftJoin('materiel_class as e', 'e.id', '=', 'd.materiel_class_id')
                                ->leftJoin('sell_package_content as g', 'g.materiel_type_id', '=', 'a.goods_id')
                                ->where('b.id', $number_info['storage_manage_id'])
                                ->where('g.id', $val['package_content_id'])
                                ->where('a.serial_no', $serial_data)
                                ->where('b.delete_flag', 0)
                                ->where('g.sell_id', $id)
                                ->first();

                                $val['num'] = 1;
                                //销售单商品出库记录
                                $sellOutStorageInfo = SellOutStorageModel::where([
                                    'materiel_type_id' => $storageBatchInfo['materiel_type_id'],
                                    'sell_id' => $id
                                ])->first();

                                MessageService::sendAlertSms(
                                    $storageBatchInfo['materiel_name'],
                                    $storageBatchInfo['type_name'],
                                    $storageBatchInfo['in_storage_num'] - ($val['num']),
                                    $storageBatchInfo['alert_num'],
                                    $data,
                                    $storageBatchInfo['storage_id'],
                                    $storageBatchInfo['storage_name'],
                                    $val['num']
                                    );

                                MessageService::sendShortSms(
                                    $storageBatchInfo['materiel_name'],
                                    $storageBatchInfo['type_name'],
                                    $storageBatchInfo['in_storage_num'] - ($val['num']),
                                    $data,
                                    $storageBatchInfo['storage_name'],
                                    $storageBatchInfo['storage_id']
                                    );

                                MessageService::sendOutSms(
                                    $storageBatchInfo['materiel_name'],
                                    $storageBatchInfo['type_name'],
                                    $storageBatchInfo['in_storage_num'] - ($val['num']),
                                    $storageBatchInfo['storage_name'],
                                    $val['num'],
                                    $data,
                                    $storageBatchInfo['storage_id'],
                                    $storageBatchInfo['alert_num'],
                                    );
                                //出库记录
                                $logPackageContentInfo[] = [
                                    'log_package_id' => $logPackageId,
                                    'package_id' => $value['package_id'],
                                    'storage_id' => $storageBatchInfo['storage_id'],
                                    'storage_name' => $storageBatchInfo['storage_name'],
                                    'storage_address' => $storageBatchInfo['storage_address'],
                                    'materiel_class_id' => $storageBatchInfo['materiel_class_id'],
                                    'materiel_class_name' => $storageBatchInfo['class_name'],
                                    'materiel_class_no' => $storageBatchInfo['class_no'],
                                    'materiel_type_id' => $storageBatchInfo['materiel_type_id'],
                                    'materiel_name' => $storageBatchInfo['materiel_name'],
                                    'type_name' => $storageBatchInfo['type_name'],
                                    'materiel_no' => $storageBatchInfo['materiel_no'],
                                    'operate_num' => $val['num'],
                                    'out_storage_manage_id' => $storageBatchInfo['storage_manage_id'],
                                    'last_storage_num' => $storageBatchInfo['in_storage_num'],
                                    'next_storage_num' => $storageBatchInfo['in_storage_num']- ($val['num']),
                                    'all_id_type' => 4,
                                    'all_id' => $id,
                                    'user_id' => $data['user_id'],
                                    'main_id' => $data['main_id'],
                                    'created_at' => time(),
                                    'serial_number' => $serial_data
                                ];

                                $sellGoodsList[] = [
                                    'materiel_type_id' => $storageBatchInfo['materiel_type_id'],
                                    'cost_price' => $storageBatchInfo['materiel_mean_cost'],
                                    'num' => $val['num'],
                                    'main_id' => $data['main_id'],
                                    'user_id' => $data['user_id'],
                                    'sell_id' => $id,
                                    'sell_date' => strtotime($sellInfo['sell_date']),
                                    'created_at' => time(),
                                ];

                                StorageManageModel::where('id', $storageBatchInfo['storage_manage_id'])
                                ->update([
                                    'in_storage_num' => DB::raw("in_storage_num - ".$val['num']),
                                ]);

                                $prepareInfo = SellPackagePrepareOutLogModel::where([
                                    'sell_id' => $id,
                                    'package_id' => $value['package_id'],
                                ])
                                ->first();

                                if(empty($prepareInfo)) {
                                    StorageManageModel::where('id', $storageBatchInfo['storage_manage_id'])
                                    ->decrement('virtual_storage_num', $val['num']);
                                }
                                SellPackageContentModel::where('id', $storageBatchInfo['sell_package_content_id'])
                                ->decrement('rest_num', $val['num']);
                        }
                    }else{
                $num = 0;
                if(!empty($val['batch_info'])){
                    foreach($val['batch_info'] as $v) {
                        $num += $v['num'];

                        $storageBatchInfo = StorageBatchModel::select(
                            'a.id',
                            'b.id as storage_manage_id',
                            'batch_no',
                            'batch_left_num',
                            'b.storage_id',
                            'c.storage_name',
                            'c.storage_address',
                            'b.materiel_mean_cost',
                            'b.type_id as materiel_type_id',
                            'd.materiel_name',
                            'd.type_name',
                            'd.materiel_no',
                            'b.materiel_class_id',
                            'e.class_name',
                            'e.class_no',
                            'in_storage_num',
                            'alert_num',
                            'f.id as sid',
                            'sell_package_content_id',
                            'f.rest_num'
                        )
                            ->from('storage_batch as a')
                            ->leftJoin('storage_manage as b', 'b.id', '=', 'a.storage_manage_id')
                            ->leftJoin('storage as c', 'c.id', '=', 'b.storage_id')
                            ->leftJoin('materiel_type as d', 'd.id', '=', 'b.type_id')
                            ->leftJoin('materiel_class as e', 'e.id', '=', 'd.materiel_class_id')
                            ->leftJoin('sell_package_batch as f', 'f.storage_manage_id', '=', 'b.id')
                            ->leftJoin('sell_package_content as g', 'g.id', '=', 'f.sell_package_content_id')
                            ->where('b.id', $v['storage_manage_id'])
                            ->where('g.id', $val['package_content_id'])
                            ->where('a.id', $v['batch_id'])
                            ->where('b.delete_flag', 0)
                            ->where('f.sell_id', $id)
                            ->first();

                        if(empty($storageBatchInfo)) {
                            throw new Exception('套餐内商品暂无指定的库存信息，请查验后重试');
                        }

                        if($storageBatchInfo['batch_left_num'] < $v['num']) {
                            throw new Exception('批次剩余数量不足,无法出库');
                        }

                        if($storageBatchInfo['in_storage_num'] < $v['num']) {
                            throw new Exception('库存数量不足,无法出库');
                        }

                        MessageService::sendAlertSms(
                            $storageBatchInfo['materiel_name'],
                            $storageBatchInfo['type_name'],
                            $storageBatchInfo['in_storage_num'] - ($v['num']),
                            $storageBatchInfo['alert_num'],
                            $data,
                            $storageBatchInfo['storage_id'],
                            $storageBatchInfo['storage_name'],
                            $v['num']
                        );

                        MessageService::sendShortSms(
                            $storageBatchInfo['materiel_name'],
                            $storageBatchInfo['type_name'],
                            $storageBatchInfo['in_storage_num'] - ($v['num']),
                            $data,
                            $storageBatchInfo['storage_name'],
                            $storageBatchInfo['storage_id']
                        );

                        MessageService::sendOutSms(
                            $storageBatchInfo['materiel_name'],
                            $storageBatchInfo['type_name'],
                            $storageBatchInfo['in_storage_num'] - ($v['num']),
                            $storageBatchInfo['storage_name'],
                            $v['num'],
                            $data,
                            $storageBatchInfo['storage_id'],
                            $storageBatchInfo['alert_num'],
                        );

                        $logPackageContentInfo[] = [
                            'log_package_id' => $logPackageId,
                            'package_id' => $value['package_id'],
                            'storage_id' => $storageBatchInfo['storage_id'],
                            'storage_name' => $storageBatchInfo['storage_name'],
                            'storage_address' => $storageBatchInfo['storage_address'],
                            'materiel_class_id' => $storageBatchInfo['materiel_class_id'],
                            'materiel_class_name' => $storageBatchInfo['class_name'],
                            'materiel_class_no' => $storageBatchInfo['class_no'],
                            'materiel_type_id' => $storageBatchInfo['materiel_type_id'],
                            'materiel_name' => $storageBatchInfo['materiel_name'],
                            'type_name' => $storageBatchInfo['type_name'],
                            'materiel_no' => $storageBatchInfo['materiel_no'],
                            'operate_num' => $v['num'],
                            'out_storage_manage_id' => $storageBatchInfo['storage_manage_id'],
                            'storage_batch_id' => $v['batch_id'],
                            'last_storage_num' => $storageBatchInfo['in_storage_num'],
    //                        'next_storage_num' => $storageBatchInfo['in_storage_num']- $outNum,
                            'next_storage_num' => $storageBatchInfo['in_storage_num']- ($v['num']),
                            'all_id_type' => 4,
                            'all_id' => $id,
                            'user_id' => $data['user_id'],
                            'main_id' => $data['main_id'],
                            'created_at' => time()
                        ];

                        $sellGoodsList[] = [
                            'materiel_type_id' => $storageBatchInfo['materiel_type_id'],
                            'cost_price' => $storageBatchInfo['materiel_mean_cost'],
                            'num' => $v['num'],
                            'main_id' => $data['main_id'],
                            'user_id' => $data['user_id'],
                            'sell_id' => $id,
                            'sell_date' => strtotime($sellInfo['sell_date']),
                            'created_at' => time(),
                        ];

                        $prepareInfo = SellPackagePrepareOutLogModel::where([
                            'sell_id' => $id,
                            'package_id' => $value['package_id'],
                        ])
                            ->first();

                        if(empty($prepareInfo)) {
                            StorageManageModel::where('id', $storageBatchInfo['storage_manage_id'])
                                ->decrement('virtual_storage_num', $v['num']);
                        }

                        StorageManageModel::where('id', $storageBatchInfo['storage_manage_id'])
                            ->update([
                                'in_storage_num' => DB::raw("in_storage_num - ".$v['num'])
                            ]);

                        StorageBatchModel::where('id', $v['batch_id'])
                            ->decrement('batch_left_num', $v['num']);

                        SellPackageBatchModel::where('id', $storageBatchInfo['sid'])
                            ->decrement('rest_num', $v['num']);

                        SellPackageContentModel::where('id', $storageBatchInfo['sell_package_content_id'])
                            ->decrement('rest_num', $v['num']);
                    }

                    if($val['num'] > $num) {
                        throw new Exception('套餐内商品批次设置的数量不足，无法出库,实际所需:'.$val['num'].'已设置数量:'.$num);
                    }
                }
                }
            }
        }

        LogPackageContentModel::insert($logPackageContentInfo);

        return true;
    }

    static private function sellPackagePart1($id, $package, $data)
    {
        $logPackageContentInfo = [];
        $totalMaterielNum = 0;
        $totalBatchNum = 0;

        foreach($package as $value) {
            //销售单套餐信息
            $packageDetailInfo = SellPackageDetailModel::select(
                'a.id',
                'b.package_name',
                'num',
                'out_num',
                'price'
            )
                ->from('sell_package_detail as a')
                ->leftJoin('package as b', 'b.id', '=', 'a.package_id')
                ->where([
                    'package_id' => $value['package_id'],
                    'sell_id' => $id
                ])
                ->whereRaw('num > out_num')
                ->first();

            if(empty($packageDetailInfo)) {
                throw new Exception('套餐已全部出库，无法重复操作');
            }

            if(($packageDetailInfo['num'] - $packageDetailInfo['out_num']) < $value['num']) {
                throw new Exception('套餐:'.$packageDetailInfo['package_name'].'可出库数量不足，当前剩余:'.($packageDetailInfo['num'] - $packageDetailInfo['out_num']));
            }

            SellPackageDetailModel::where([
                'id' => $packageDetailInfo['id'],
                'sell_id' => $id
            ])
                ->increment('out_num', $value['num']);

            $logPackageId = LogPackageModel::insertGetId([
                'package_id' => $value['package_id'],
                'package_name' => $packageDetailInfo['package_name'],
                'num' => $value['num'],
                'sell_price' => $value['price'],
                'cost' => sprintf('%.6f', OutInRepealService::getPackageCost($id, $value['package_id']) * $value['num']),
                'out_storage_time' => strtotime($data['in_storage_time']),
                'all_id_type' => 2,
                'all_id' => $id,
                'user_id' => $data['user_id'],
                'main_id' => $data['main_id'],
                'remark' => empty($value['remark'])?'':$value['remark'],
                'created_at' => time()
            ]);

            foreach($value['package_content'] as $val) {
                $packageContentInfo = SellPackageContentModel::select(
                    'a.id',
                    'b.id as materiel_type_id',
                    'num',
                    'materiel_name',
                    'type_name',
                    'rest_num'
                )
                    ->from('sell_package_content as a')
                    ->leftJoin('materiel_type as b', 'b.id', '=', 'a.materiel_type_id')
                    ->where('a.id', $val['package_content_id'])->first();

                if(empty($val['batch_info'])) {
                    throw new Exception('请设置批次后再次操作');
                }

                $outNum = $value['num'] * $val['num'];

                foreach($val['batch_info'] as $v) {
                    $storageBatchInfo = StorageBatchModel::select(
                        'a.id',
                        'b.id as storage_manage_id',
                        'batch_no',
                        'batch_left_num',
                        'b.storage_id',
                        'c.storage_name',
                        'c.storage_address',
                        'b.type_id as materiel_type_id',
                        'd.materiel_name',
                        'd.type_name',
                        'd.materiel_no',
                        'b.materiel_class_id',
                        'e.class_name',
                        'e.class_no',
                        'in_storage_num',
                        'alert_num',
                        'f.id as sid',
                        'sell_package_content_id',
                        'f.rest_num'
                    )
                        ->from('storage_batch as a')
                        ->leftJoin('storage_manage as b', 'b.id', '=', 'a.storage_manage_id')
                        ->leftJoin('storage as c', 'c.id', '=', 'b.storage_id')
                        ->leftJoin('materiel_type as d', 'd.id', '=', 'b.type_id')
                        ->leftJoin('materiel_class as e', 'e.id', '=', 'd.materiel_class_id')
                        ->leftJoin('sell_package_batch as f', 'f.storage_manage_id', '=', 'b.id')
                        ->leftJoin('sell_package_content as g', 'g.id', '=', 'f.sell_package_content_id')
                        ->where('b.id', $v['storage_manage_id'])
                        ->where('g.id', $val['package_content_id'])
                        ->where('a.id', $v['batch_id'])
                        ->where('b.delete_flag', 0)
                        ->where('f.sell_id', $id)
                        ->first()->toArray();

                    if(empty($storageBatchInfo)) {
                        throw new Exception('套餐内商品暂无指定的库存信息，请查验后重试');
                    }

                    if($outNum > $storageBatchInfo['batch_left_num']) {
                        throw new Exception('批次剩余数量不足,无法出库');
                    }

                    if($outNum > $storageBatchInfo['rest_num']) {
                        throw new Exception('套餐内商品批次设置的数量不足，无法出库,实际所需:'.$outNum.'已设置数量:'.$storageBatchInfo['rest_num']);
                    }

                    if($outNum > $storageBatchInfo['in_storage_num']) {
                        throw new Exception('库存剩余数量不足,无法出库');
                    }

                    MessageService::sendAlertSms(
                        $storageBatchInfo['materiel_name'],
                        $storageBatchInfo['type_name'],
                        $storageBatchInfo['in_storage_num'] - ($v['num'] * $value['num']),
                        $storageBatchInfo['alert_num'],
                        $data,
                        $storageBatchInfo['storage_id'],
                        $storageBatchInfo['storage_name'],
                        $v['num'] * $value['num']
                    );

                    MessageService::sendShortSms(
                        $storageBatchInfo['materiel_name'],
                        $storageBatchInfo['type_name'],
                        $storageBatchInfo['in_storage_num'] - ($v['num'] * $value['num']),
                        $data,
                        $storageBatchInfo['storage_name'],
                        $storageBatchInfo['storage_id']
                    );

                    MessageService::sendOutSms(
                        $storageBatchInfo['materiel_name'],
                        $storageBatchInfo['type_name'],
                        $storageBatchInfo['in_storage_num'] - ($v['num'] * $value['num']),
                        $storageBatchInfo['storage_name'],
                        $v['num'] * $value['num'],
                        $data,
                        $storageBatchInfo['storage_id'],
                        $storageBatchInfo['alert_num'],
                    );

                    $logPackageContentInfo[] = [
                        'log_package_id' => $logPackageId,
                        'package_id' => $value['package_id'],
                        'storage_id' => $storageBatchInfo['storage_id'],
                        'storage_name' => $storageBatchInfo['storage_name'],
                        'storage_address' => $storageBatchInfo['storage_address'],
                        'materiel_class_id' => $storageBatchInfo['materiel_class_id'],
                        'materiel_class_name' => $storageBatchInfo['class_name'],
                        'materiel_class_no' => $storageBatchInfo['class_no'],
                        'materiel_type_id' => $storageBatchInfo['materiel_type_id'],
                        'materiel_name' => $storageBatchInfo['materiel_name'],
                        'type_name' => $storageBatchInfo['type_name'],
                        'materiel_no' => $storageBatchInfo['materiel_no'],
                        'operate_num' => $outNum,
                        'out_storage_manage_id' => $storageBatchInfo['storage_manage_id'],
                        'storage_batch_id' => $v['batch_id'],
                        'last_storage_num' => $storageBatchInfo['in_storage_num'],
                        'next_storage_num' => $storageBatchInfo['in_storage_num']- $outNum,
                        'all_id_type' => 4,
                        'all_id' => $id,
                        'user_id' => $data['user_id'],
                        'main_id' => $data['main_id'],
                        'created_at' => time()
                    ];


                    $prepareInfo = SellPackagePrepareOutLogModel::where([
                        'sell_id' => $id,
                        'package_id' => $value['package_id'],
                    ])
                        ->first();

                    if(empty($prepareInfo)) {
                        StorageManageModel::where('id', $storageBatchInfo['storage_manage_id'])
                            ->decrement('virtual_storage_num', $outNum);
                    }

                    StorageManageModel::where('id', $storageBatchInfo['storage_manage_id'])
                        ->update([
                            'in_storage_num' => DB::raw("in_storage_num - ".$outNum)
                        ]);

                    StorageBatchModel::where('id', $v['batch_id'])
                        ->decrement('batch_left_num', $outNum);

                    SellPackageBatchModel::where('id', $storageBatchInfo['sid'])
                        ->decrement('rest_num', $outNum);

                    SellPackageContentModel::where('id', $storageBatchInfo['sell_package_content_id'])
                        ->decrement('rest_num', $outNum);
                }
            }
        }

        LogPackageContentModel::insert($logPackageContentInfo);

        return true;
    }

    static private function sellPackagePartStep1($paramsArr, $id, $package, $data)
    {
        $result = self::sellPackagePartStep2($paramsArr, $id, $package, $data);

        if(isset($result['code'])) {
            return $result;
        }

        //销售单套餐出库记录-更新
        if(!empty($result['data2'])) {
            foreach($result['data2'] as $value) {
                SellOutStoragePackageModel::where('id', $value['id'])
                    ->lockForUpdate()
                    ->increment('num', $value['num']);
            }

            foreach($result['data3'] as $val) {
                SellOutStoragePackageContentModel::where([
                    'sell_id' => $val['sell_id'],
                    'package_content_id' => $val['package_content_id']
                ])
                    ->lockForUpdate()
                    ->increment('num', $val['num']);
            }
        }

        //销售单套餐出库记录-新增
        if(!empty($result['data1'])) {
            foreach($result['data1'] as $v) {
                $newId = SellOutStoragePackageModel::insert($v);
                foreach($result['data3'] as &$v1) {
                    if($v['package_id'] == $v1['package_id']) {
                        unset($v1['package_id']);
                        $v1['o_s_package_id'] = $newId;
                        SellOutStoragePackageContentModel::insert($v1);
                    }
                }
            }
        }

        //扣除销售单套餐数量
        if(!empty($result['data4'])) {
            foreach($result['data4'] as $v2) {
                SellPackageDetailModel::where([
                    'package_id' => $v2['package_id'],
                    'sell_id' => $id
                ])->lockForUpdate()->increment('out_num', $v2['num']);
            }
        }

        //扣除销售单套餐数量
        if(!empty($result['data5'])) {
            foreach($result['data5'] as $v3) {
                SellPackageContentModel::where([
                    'id' => $v3['package_content_id'],
                    'sell_id' => $id
                ])->lockForUpdate()->decrement('total_left_num', $v3['total_num']);
            }
        }

        if(!empty($result['data']['content'])) {
            foreach($result['data']['content'] as $v4) {
                foreach($v4['package_info'] as $v5) {
                    $packageInfo = PackageModel::where('id', $v5['package_id'])->first();

                    $logPackageId = LogPackageModel::insertGetId([
                        'package_id' => $packageInfo['id'],
                        'package_name' => $packageInfo['package_name'],
                        'num' => $v5['num'],
                        'all_id_type' => 2,
                        'all_id' => $id,
                        'user_id' => $data['user_id'],
                        'main_id' => $data['main_id'],
                        'remark' => $v5['remark'],
                        'created_at' => time(),
                    ]);

                    foreach($v5['batch_info'] as $v6) {
                        //出库商品基础信息
                        $storageManageInfo = StorageManageModel::select(
                            'a.id',
                            'a.storage_id',
                            'b.storage_name',
                            'b.storage_address',
                            'a.type_id',
                            'c.materiel_name',
                            'c.materiel_no',
                            'c.type_name',
                            'a.materiel_class_id',
                            'd.class_name',
                            'd.class_no',
                            'materiel_mean_cost',
                            'in_storage_num'
                        )
                            ->from('storage_manage as a')
                            ->leftJoin('storage as b', 'b.id', '=', 'a.storage_id')
                            ->leftJoin('materiel_type as c', 'c.id', '=', 'a.type_id')
                            ->leftJoin('materiel_class as d', 'd.id', '=', 'c.materiel_class_id')
                            ->where([
                                'a.id' => $v6['storage_manage_id'],
                                'a.delete_flag' => 0
                            ])->first();

                        if (($v6['num'] * $v5['num']) > $storageManageInfo['in_storage_num']) {
                            return [
                                'code' => 1,
                                'msg' => '商品:' . $storageManageInfo['materiel_name'] . '-' . $storageManageInfo['type_name'] . ',库存数不足',
                                'data' => ''
                            ];
                        }

                        LogPackageContentModel::insert([
                            'log_package_id' => $logPackageId,
                            'package_id' => $packageInfo['id'],
                            'storage_id' => $storageManageInfo['storage_id'],
                            'storage_name' => $storageManageInfo['storage_name'],
                            'storage_address' => $storageManageInfo['storage_address'],
                            'materiel_class_id' => $storageManageInfo['materiel_class_id'],
                            'materiel_class_name' => $storageManageInfo['class_name'],
                            'materiel_class_no' => $storageManageInfo['class_no'],
                            'materiel_type_id' => $storageManageInfo['type_id'],
                            'materiel_name' => $storageManageInfo['materiel_name'],
                            'type_name' => $storageManageInfo['type_name'],
                            'operate_num' => $v6['num'] * $v5['num'],
                            'out_storage_manage_id' => $v6['storage_manage_id'],
                            'storage_batch_id' => $v6['batch_id'],
                            'last_storage_num' => $storageManageInfo['in_storage_num'],
                            'next_storage_num' => $storageManageInfo['in_storage_num'] - ($v6['num'] * $v5['num']),
                            'all_id_type' => 4,
                            'all_id' => $id,
                            'user_id' => $data['user_id'],
                            'main_id' => $data['main_id'],
                            'created_at' => time(),
                        ]);

                        $sellPackageBatchInfo = SellPackageBatchModel::where([
                            'sell_package_content_id' => $v6['package_content_id'],
                            'sell_id' => $id
                        ])->first();

                        if(empty($sellPackageBatchInfo)) {
                            return [
                                'code' => 1,
                                'msg' => '批次信息不存在',
                                'data' => ''
                            ];
                        }

                        if($sellPackageBatchInfo['rest_num'] < ($v6['num'] * $v5['num'])) {
                            return ['code' => 1, 'msg' => '销售单内套餐商品可出库批次数不足', 'data' => ''];
                        }

                        SellPackageBatchModel::where([
                            'sell_package_content_id' => $v6['package_content_id'],
                            'sell_id' => $id
                        ])
                            ->lockForUpdate()
                            ->decrement('rest_num', ($v6['num'] * $v5['num']));

                        $info = StorageBatchModel::where('id', $v6['batch_id'])->first();

                        if($info['batch_num'] < $v6['num']) {
                            return ['code' => 1, 'msg' => '商品批次数不足，无法出库', 'data' => ''];
                        }

                        StorageManageModel::where('id', $v6['storage_manage_id'])
                            ->lockForUpdate()
                            ->update([
                                'in_storage_num' => DB::raw("in_storage_num - ".($v6['num'] * $v5['num'])),
                                'virtual_storage_num' => DB::raw("virtual_storage_num - ".($v6['num'] * $v5['num']))
                            ]);
                    }
                }
            }
        }

        return ['code' => 0, 'msg' => 'success', 'data' => ''];
    }

    static private function sellPackagePartStep2($paramsArr, $id, $packageInfo, $data)
    {
        $sellPackageOutStorageNewData = [];
        $sellPackageOutStorageAgainData = [];
        foreach($packageInfo as $key => $value) {
            //销售单套餐信息
            $sellPackageInfo = SellPackageDetailModel::where([
                'sell_id' => $id,
                'package_id' => $value['package_id']
            ])
                ->first();

            $packageOutInfo[$key] = [
                'package_id' => $value['package_id'],
                'num' => $value['num']
            ];

            if(($sellPackageInfo['num'] - $sellPackageInfo['out_num']) < $value['num']) {
                return ['code' => 1, 'msg' => '销售单内可出库套餐数量不足，请重试', 'data' => ''];
            }

            $packageContentInfos = SellPackageContentModel::where([
                'sell_id' => $id,
                'package_id' => $value['package_id']
            ])->get()->toArray();

            foreach($packageContentInfos as $k => $val) {
                $materielTypeInfo = MaterielsTypeModel::select(
                    'a.id',
                    'a.materiel_name',
                    'a.type_name',
                )
                    ->from('materiel_type as a')
                    ->leftJoin('sell_package_content as b', 'a.id', '=', 'b.materiel_type_id')
                    ->where('a.id', $val['id'])
                    ->first();

                $totalBatchNum = 0;
                foreach($value['batch_info'] as $v) {
                    $paramsArr['content'][$key]['package_info'][] = [
                        'package_id' => $value['package_id'],
                        'num' => $value['num'],
                        'price' => $value['price'],
                        'remark' => $value['remark'],
                    ];

                    $paramsArr['content'][$key]['package_info'][$key]['batch_info'][] =  [
                        'batch_id' => $v['batch_id'],
                        'num' => $v['num'],
                        'storage_manage_id' => $v['storage_manage_id'],
                        'package_content_id' => $val['id']
                    ];

                    //批次号信息
                    $BatchInfo = StorageBatchModel::where('id', $v['batch_id'])->first();

                    if($v['num'] > $BatchInfo['batch_num']) {
                        return [
                            'code' => 1,
                            'msg' => '批次号:'.$BatchInfo['batch_no'].'库存数量不足，无法完成出库操作',
                            'data' => ''
                        ];
                    }

                    //验证单个商品批次总数是否与该商品所需出库数量相符
                    if($val['num'] < $v['num']) {
                        return [
                            'code' => 1,
                            'msg' => '商品:'.
                                $materielTypeInfo['materiel_name'].'-'.$materielTypeInfo['type_name'].
                                '批次出库数量超出该商品需出库数量,批次数量:'.$v['num'].',超出数量:'.($v['num'] - $val['num']),
                            'data' => ''
                        ];
                    }

                    $packageBatchInfo = SellPackageBatchModel::where([
                        'sell_id' => $id,
                        'storage_batch_id' => $v['batch_id'],
                    ])
                        ->first();

                    if($v['num'] > $packageBatchInfo['rest_num']) {
                        return [
                            'code' => 1,
                            'msg' => '销售单内套餐商品存在批次数量不足的情况，无法完成出库',
                            'data' => ''
                        ];
                    }
                }

                $sellPackageContentInfo = SellPackageContentModel::where('id', $val['id'])->first();
                $sellPackageContentOutData[$key]['package_id'] = $value['package_id'];
                $sellPackageContentOutData[$key]['type_id'] = $sellPackageContentInfo['type_id'];
                $sellPackageContentOutData[$key]['storage_id'] = $sellPackageContentInfo['storage_id'];
                $sellPackageContentOutData[$key]['package_content_id'] = $sellPackageContentInfo['id'];
                $sellPackageContentOutData[$key]['storage_manage_id'] = $sellPackageContentInfo['storage_manage_id'];
                $sellPackageContentOutData[$key]['sell_id'] = $id;
                $sellPackageContentOutData[$key]['num'] = $val['num'];
                $sellPackageContentOutData[$key]['user_id'] = $data['user_id'];
                $sellPackageContentOutData[$key]['main_id'] = $data['main_id'];
                $sellPackageContentOutData[$key]['created_at'] = time();
            }

            $packageContentInfo[$k]['package_content_id'] = $val['id'];
            $packageContentInfo[$k]['total_num'] = $val['num'] * $value['num'];

            $sellPackageOutStorageInfo = SellOutStoragePackageModel::where([
                'package_id' => $value['package_id'],
                'sell_id' => $id
            ])->first();

            if(empty($sellPackageOutStorageInfo)) {
                $sellPackageOutStorageNewData[$key]['sell_id'] = $id;
                $sellPackageOutStorageNewData[$key]['package_id'] = $value['package_id'];
                $sellPackageOutStorageNewData[$key]['price'] = $value['price'];
                $sellPackageOutStorageNewData[$key]['num'] = $value['num'];
                $sellPackageOutStorageNewData[$key]['remark'] = empty($value['remark'])?'':$value['remark'];
            }
            else {
                $sellPackageOutStorageAgainData[$key]['id'] = $sellPackageOutStorageInfo['id'];
                $sellPackageOutStorageAgainData[$key]['num'] = $totalBatchNum;
            }
        }

        return [
            'data' => $paramsArr,
            'data1' => $sellPackageOutStorageNewData,
            'data2' => $sellPackageOutStorageAgainData,
            'data3' => $sellPackageContentOutData,
            'data4' => $packageOutInfo,
            'data5' => $packageContentInfo
        ];
    }

    static private function selMaterielPartStep1($id, $goods, $data, $isUseShelf)
    {
        $sellOutStorageNewData = [];
        $sellOutStorageAgainData = [];
        $outStorageLogInfo = [];
        $logOutPackageInfo = [];
        $sellGoodsList = [];

        $sellInfo = SellModel::where('id', $id)->first();

        foreach($goods as $value) {
            $totalBatchNum = 0;//商品总批次数量

            $sellGoodsDetailInfo = SellGoodsDetailModel::where([
                'materiel_type_id' => $value['materiel_type_id'],
                'warehouse_id' => $value['warehouse_id'],
                'sell_id' => $id
            ])
                ->first()->toArray();

            //剩余可出库数量
            $restNum = $sellGoodsDetailInfo['num'] - $sellGoodsDetailInfo['out_num'];

            //查询商品信息
            $minfo = MaterielsTypeModel::select('is_use_serial')->where('id', $value['materiel_type_id'])->first();

            if($minfo['is_use_serial'] == 1){
                $serial_no_array = explode(',',$value['serial_no']);

                if(empty($serial_no_array)){
                    throw new Exception('序列号不能为空');
                }

                if(count($serial_no_array) != $value['num']){
                    throw new Exception('序列号个数与入库数量不符');
                }
                $outStorageLogInfo = [];
                foreach ($serial_no_array as $k => $serial_data){
                    //检查序列号是否使用
                    $number_info = SerialNumberModel::where(['goods_id' => $value['materiel_type_id'],'serial_no' => $serial_data,'status' => SerialNumberModel::USEDSTATUS])->first();

                    if($number_info){
                        throw new Exception('该商品：'.$value['materiel_type_id'].'的序列号：'.$serial_data.'已被使用');
                    }

                   SellOutSerialNumbersModel::insert([

                        'main_id' =>  $data['main_id'],
                        'created_at' => time(),
                        'sell_id' => $data['id'],
                        'type_id' => $value['materiel_type_id'],
                        'serial_number' => $serial_data,
                        'status' => 1
                    ]);

                    SerialNumberModel::where(['serial_no' => $serial_data,'status' => SerialNumberModel::UNUSEDSTATUS,
                        'goods_id' => $value['materiel_type_id'],
                    ])->update(['status' => SerialNumberModel::USEDSTATUS]);

                    $storageBatchInfo = SerialNumberModel::select(
                        'a.id',
                        'b.id as storage_manage_id',
                        'in_storage_num',
                        'materiel_mean_cost',
                        'type_id as materiel_type_id',
                        'c.materiel_name',
                        'c.type_name',
                        'c.materiel_no',
                        'storage_id',
                        'd.storage_name',
                        'd.storage_address',
                        'alert_num',
                        'b.materiel_class_id',
                        'class_name',
                        'class_no',
                        'b.shelf_id',
                        'b.location_id'
                        )
                        ->from('serial_number as a')
                        ->leftJoin('storage_manage as b', 'a.storage_manage_id', '=', 'b.id')
                        ->leftJoin('materiel_type as c', 'c.id', '=', 'b.type_id')
                        ->leftJoin('storage as d', 'd.id', '=', 'b.storage_id')
                        ->leftJoin('materiel_class as e', 'e.id', '=', 'c.materiel_class_id')
                        ->leftJoin('sell_goods_detail as g', 'g.materiel_type_id', '=', 'a.goods_id')
                        ->where('a.serial_no', $serial_data);

                    if($isUseShelf) {
                        $shelfId = !empty($value['shelf_id'])?$value['shelf_id']:0;
                        $locationId = !empty($value['location_id'])?$value['location_id']:0;
                        $storageBatchInfo->where('b.shelf_id', $shelfId);
                        $storageBatchInfo->where('b.location_id', $locationId);
                    }

                    $storageBatchInfo = $storageBatchInfo->where('g.id', $sellGoodsDetailInfo['id'])
                        ->where('b.delete_flag', 0)
                        ->first();

                    if(empty($storageBatchInfo)) {
                        throw new Exception('库存商品:'.$storageBatchInfo['materiel_name'].'-'.$storageBatchInfo['type_name'].'不存在');
                    }

                        $val['num'] = 1;
                            //销售单商品出库记录
                            $sellOutStorageInfo = SellOutStorageModel::where([
                                'materiel_type_id' => $value['materiel_type_id'],
                                'sell_id' => $id
                            ])->first();

                            //出库记录
                            $outStorageLogInfo[] = [
                                'storage_id' => $storageBatchInfo['storage_id'],
                                'storage_name' => $storageBatchInfo['storage_name'],
                                'storage_address' => $storageBatchInfo['storage_address'],
                                'curr_storage_manage_id' => $storageBatchInfo['storage_manage_id'],
                                'materiel_class_id' => $storageBatchInfo['materiel_class_id'],
                                'materiel_class_name' => $storageBatchInfo['class_name'],
                                'materiel_class_no' => $storageBatchInfo['class_no'],
                                'materiel_type_id' => $storageBatchInfo['materiel_type_id'],
                                'materiel_name' => $storageBatchInfo['materiel_name'],
                                'type_name' => $storageBatchInfo['type_name'],
                                'materiel_no' => $storageBatchInfo['materiel_no'],
                                'operate_num' => $val['num'],
                                'last_storage_num' => $storageBatchInfo['in_storage_num'],
                                'next_storage_num' => $storageBatchInfo['in_storage_num'] - $val['num'],
                                'sell_price' => $value['price'],
                                'materiel_mean_cost' => $storageBatchInfo['materiel_mean_cost'],
                                'all_id_type' => 2,
                                'all_id' => $id,
                                'user_id' => $data['user_id'],
                                'main_id' => $data['main_id'],
                                'remark' => $value['remark'],
                                'out_storage_time' => empty($data['in_storage_time'])?time():strtotime($data['in_storage_time']),
                                'fact_out_time' => time(),
                                'created_at' => time(),
                                'serial_number' => $serial_data,
                                'shelf_id' => $storageBatchInfo['shelf_id'],
                                'location_id' => $storageBatchInfo['location_id'],
                            ];

                            $sellGoodsList[] = [
                                'materiel_type_id' => $storageBatchInfo['materiel_type_id'],
                                'cost_price' => $storageBatchInfo['materiel_mean_cost'],
                                'num' => 1,
                                'main_id' => $data['main_id'],
                                'user_id' => $data['user_id'],
                                'sell_id' => $id,
                                'sell_date' => strtotime($sellInfo['sell_date']),
                                'created_at' => time(),
                            ];

                            //                $logOutPackageInfo[] = [
                            //                    'storage_manage_id' => $storageBatchInfo['storage_manage_id'],
                            //                    'materiel_class_id' => $storageBatchInfo['materiel_class_id'],
                            //                    'materiel_type_id' => $storageBatchInfo['materiel_type_id'],
                            //                    'storage_id' => $storageBatchInfo['storage_id'],
                            //                    'out_time' => $data['in_storage_time'],
                            //                    'num' => $val['num'],
                            //                    'mean_cost' => $storageBatchInfo['materiel_mean_cost'],
                            //                    'price' => $value['price'],
                            //                    'all_id_type' => 2,
                            //                    'all_id' => $id,
                            //                    'user_id' => $data['user_id'],
                            //                    'main_id' => $data['main_id'],
                            //                    'created_at' => time(),
                            //                ];

                            //验证是否已经出库
                            if(empty($sellOutStorageInfo)) {
                                $sellOutStorageNewData[$k]['sell_id'] = $id;
                                $sellOutStorageNewData[$k]['name'] = $storageBatchInfo['materiel_name'];
                                $sellOutStorageNewData[$k]['type_name'] = $storageBatchInfo['type_name'];
                                $sellOutStorageNewData[$k]['num'] = count($serial_no_array);
                                $sellOutStorageNewData[$k]['price'] = $value['price'];
                                $sellOutStorageNewData[$k]['warehouse'] = $storageBatchInfo['storage_name'];
                                $sellOutStorageNewData[$k]['warehouse_id'] = $storageBatchInfo['storage_id'];
                                $sellOutStorageNewData[$k]['materiel_type_id'] = $storageBatchInfo['materiel_type_id'];
                                $sellOutStorageNewData[$k]['remark'] = empty($value['remark'])?'':$value['remark'];
                            }
                            else {
                                $sellOutStorageAgainData[$k]['id'] = $sellOutStorageInfo['id'];
                                $sellOutStorageAgainData[$k]['num'] = $totalBatchNum;
                            }

                            StorageManageModel::where('id', $storageBatchInfo['storage_manage_id'])
                            ->update([
                                'in_storage_num' => DB::raw("in_storage_num - ".$val['num']),
                            ]);

                            $prepareInfo = SellMaterielPrepareOutLogModel::where([
                                'sell_id' => $id,
                                'materiel_type_id' => $storageBatchInfo['materiel_type_id'],
                            ])
                            ->first();

                            if(empty($prepareInfo)) {
                                StorageManageModel::where('id', $storageBatchInfo['storage_manage_id'])
                                ->decrement('virtual_storage_num', $val['num']);
                            }

                            MessageService::sendAlertSms(
                                $storageBatchInfo['materiel_name'],
                                $storageBatchInfo['type_name'],
                                $storageBatchInfo['in_storage_num'] - $val['num'],
                                $storageBatchInfo['alert_num'],
                                $data,
                                $storageBatchInfo['storage_id'],
                                $storageBatchInfo['storage_name'],
                                $val['num']
                                );

                            MessageService::sendShortSms(
                                $storageBatchInfo['materiel_name'],
                                $storageBatchInfo['type_name'],
                                $storageBatchInfo['in_storage_num'] - $val['num'],
                                $data,
                                $storageBatchInfo['storage_name'],
                                $storageBatchInfo['storage_id'],
                                );

                            MessageService::sendOutSms(
                                $storageBatchInfo['materiel_name'],
                                $storageBatchInfo['type_name'],
                                $storageBatchInfo['in_storage_num'] - $val['num'],
                                $storageBatchInfo['storage_name'],
                                $val['num'],
                                $data,
                                $storageBatchInfo['storage_id'],
                                $storageBatchInfo['alert_num'],
                                );

                            SellGoodsDetailModel::where('id', $sellGoodsDetailInfo['id'])
                            ->increment('out_num', $val['num']);

                            if(!empty($sellOutStorageNewData)) {
                                SellOutStorageModel::insert($sellOutStorageNewData);
                            }

                            if(!empty($sellOutStorageAgainData)) {
                                foreach($sellOutStorageAgainData as $v) {
                                    SellOutStorageModel::where('id', $v['id'])
                                    ->increment('num', $v['num']);
                                }
                            }
                }
                LogOutStorageModel::insert($outStorageLogInfo);
            }else{
                $outStorageLogInfo = [];
                if(!empty($value['batch_info'])){
                foreach($value['batch_info'] as $k => $val) {
                    $totalBatchNum += $val['num'];

                    $storageBatchInfo = StorageBatchModel::select(
                        'a.id',
                        'b.id as storage_manage_id',
                        'in_storage_num',
                        'materiel_mean_cost',
                        'type_id as materiel_type_id',
                        'c.materiel_name',
                        'c.type_name',
                        'c.materiel_no',
                        'storage_id',
                        'd.storage_name',
                        'd.storage_address',
                        'alert_num',
                        'batch_left_num',
                        'b.materiel_class_id',
                        'class_name',
                        'class_no',
                        'f.id as sid'
                    )
                        ->from('storage_batch as a')
                        ->leftJoin('storage_manage as b', 'a.storage_manage_id', '=', 'b.id')
                        ->leftJoin('materiel_type as c', 'c.id', '=', 'b.type_id')
                        ->leftJoin('storage as d', 'd.id', '=', 'b.storage_id')
                        ->leftJoin('materiel_class as e', 'e.id', '=', 'b.materiel_class_id')
                        ->leftJoin('sell_goods_detail_batch as f', 'f.storage_batch_id', '=', 'a.id')
                        ->leftJoin('sell_goods_detail as g', 'g.id', '=', 'f.sell_goods_detail_id')
                        ->where('a.id', $val['batch_id'])
                        ->where('g.id', $sellGoodsDetailInfo['id'])
                        ->where('b.delete_flag', 0)
                        ->first();

                    if(empty($storageBatchInfo)) {
                        throw new Exception('库存信息不存在，无法出库');
                    }

                    if($storageBatchInfo['materiel_type_id'] != $value['materiel_type_id']) {
                        throw new Exception('批次号对应的商品和需出库商品信息不一致，无法完成操作');
                    }

                    if($storageBatchInfo['batch_left_num'] < $val['num']) {
                        throw new Exception('商品批次库存不足，无法出库');
                    }

                    if($storageBatchInfo['in_storage_num'] < $val['num']) {
                        throw new Exception('商品库存不足，无法出库');
                    }

                    //销售单商品出库记录
                    $sellOutStorageInfo = SellOutStorageModel::where([
                        'materiel_type_id' => $value['materiel_type_id'],
                        'sell_id' => $id
                    ])->first();

                    //出库记录
                    $outStorageLogInfo[] = [
                        'storage_id' => $storageBatchInfo['storage_id'],
                        'storage_name' => $storageBatchInfo['storage_name'],
                        'storage_address' => $storageBatchInfo['storage_address'],
                        'curr_storage_manage_id' => $storageBatchInfo['storage_manage_id'],
                        'materiel_class_id' => $storageBatchInfo['materiel_class_id'],
                        'materiel_class_name' => $storageBatchInfo['class_name'],
                        'materiel_class_no' => $storageBatchInfo['class_no'],
                        'materiel_type_id' => $storageBatchInfo['materiel_type_id'],
                        'materiel_name' => $storageBatchInfo['materiel_name'],
                        'type_name' => $storageBatchInfo['type_name'],
                        'materiel_no' => $storageBatchInfo['materiel_no'],
                        'operate_num' => $val['num'],
                        'last_storage_num' => $storageBatchInfo['in_storage_num'],
                        'next_storage_num' => $storageBatchInfo['in_storage_num'] - $val['num'],
                        'sell_price' => $value['price'],
                        'materiel_mean_cost' => $storageBatchInfo['materiel_mean_cost'],
                        'all_id_type' => 2,
                        'all_id' => $id,
                        'user_id' => $data['user_id'],
                        'main_id' => $data['main_id'],
                        'remark' => $value['remark'],
                        'out_storage_time' => empty($data['in_storage_time'])?time():strtotime($data['in_storage_time']),
                        'fact_out_time' => time(),
                        'created_at' => time(),
                        'storage_batch_id' => $val['batch_id'],
                    ];

                    $sellGoodsList[] = [
                        'materiel_type_id' => $storageBatchInfo['materiel_type_id'],
                        'cost_price' => $storageBatchInfo['materiel_mean_cost'],
                        'num' => $val['num'],
                        'main_id' => $data['main_id'],
                        'user_id' => $data['user_id'],
                        'sell_id' => $id,
                        'sell_date' => strtotime($sellInfo['sell_date']),
                        'created_at' => time(),
                    ];

    //                $logOutPackageInfo[] = [
    //                    'storage_manage_id' => $storageBatchInfo['storage_manage_id'],
    //                    'materiel_class_id' => $storageBatchInfo['materiel_class_id'],
    //                    'materiel_type_id' => $storageBatchInfo['materiel_type_id'],
    //                    'storage_id' => $storageBatchInfo['storage_id'],
    //                    'out_time' => $data['in_storage_time'],
    //                    'num' => $val['num'],
    //                    'mean_cost' => $storageBatchInfo['materiel_mean_cost'],
    //                    'price' => $value['price'],
    //                    'all_id_type' => 2,
    //                    'all_id' => $id,
    //                    'user_id' => $data['user_id'],
    //                    'main_id' => $data['main_id'],
    //                    'created_at' => time(),
    //                ];

                    //验证是否已经出库
                    if(empty($sellOutStorageInfo)) {
                        $sellOutStorageNewData[$k]['sell_id'] = $id;
                        $sellOutStorageNewData[$k]['name'] = $storageBatchInfo['materiel_name'];
                        $sellOutStorageNewData[$k]['type_name'] = $storageBatchInfo['type_name'];
                        $sellOutStorageNewData[$k]['num'] = $totalBatchNum;
                        $sellOutStorageNewData[$k]['price'] = $value['price'];
                        $sellOutStorageNewData[$k]['warehouse'] = $storageBatchInfo['storage_name'];
                        $sellOutStorageNewData[$k]['warehouse_id'] = $storageBatchInfo['storage_id'];
                        $sellOutStorageNewData[$k]['materiel_type_id'] = $storageBatchInfo['materiel_type_id'];
                        $sellOutStorageNewData[$k]['remark'] = empty($value['remark'])?'':$value['remark'];
                    }
                    else {
                        $sellOutStorageAgainData[$k]['id'] = $sellOutStorageInfo['id'];
                        $sellOutStorageAgainData[$k]['num'] = $totalBatchNum;
                    }

                    StorageManageModel::where('id', $storageBatchInfo['storage_manage_id'])
                        ->update([
                            'in_storage_num' => DB::raw("in_storage_num - ".$val['num']),
                        ]);

                    $prepareInfo = SellMaterielPrepareOutLogModel::where([
                        'sell_id' => $id,
                        'materiel_type_id' => $storageBatchInfo['materiel_type_id'],
                    ])
                        ->first();

                    if(empty($prepareInfo)) {
                        StorageManageModel::where('id', $storageBatchInfo['storage_manage_id'])
                            ->decrement('virtual_storage_num', $val['num']);
                    }

                    MessageService::sendAlertSms(
                        $storageBatchInfo['materiel_name'],
                        $storageBatchInfo['type_name'],
                        $storageBatchInfo['in_storage_num'] - $val['num'],
                        $storageBatchInfo['alert_num'],
                        $data,
                        $storageBatchInfo['storage_id'],
                        $storageBatchInfo['storage_name'],
                        $val['num']
                    );

                    MessageService::sendShortSms(
                        $storageBatchInfo['materiel_name'],
                        $storageBatchInfo['type_name'],
                        $storageBatchInfo['in_storage_num'] - $val['num'],
                        $data,
                        $storageBatchInfo['storage_name'],
                        $storageBatchInfo['storage_id'],
                    );

                    MessageService::sendOutSms(
                        $storageBatchInfo['materiel_name'],
                        $storageBatchInfo['type_name'],
                        $storageBatchInfo['in_storage_num'] - $val['num'],
                        $storageBatchInfo['storage_name'],
                        $val['num'],
                        $data,
                        $storageBatchInfo['storage_id'],
                        $storageBatchInfo['alert_num'],
                    );

                    StorageBatchModel::where('id', $storageBatchInfo['id'])
                        ->decrement('batch_left_num', $val['num']);

                    SellGoodsDetailBatchModel::where('id', $storageBatchInfo['sid'])
                        ->decrement('rest_num', $val['num']);

                    SellGoodsDetailModel::where('id', $sellGoodsDetailInfo['id'])
                        ->increment('out_num', $val['num']);

                    if(!empty($sellOutStorageNewData)) {
                        SellOutStorageModel::insert($sellOutStorageNewData);
                    }

                    if(!empty($sellOutStorageAgainData)) {
                        foreach($sellOutStorageAgainData as $v) {
                            SellOutStorageModel::where('id', $v['id'])
                                ->increment('num', $v['num']);
                        }
                    }
                }
                LogOutStorageModel::insert($outStorageLogInfo);
                }
            }
        }

        SellGoodsListModel::insert($sellGoodsList);

        return ['code' => 0, 'msg' => 'success', 'data' => ''];

    }

    //批次号商品部分出库第二步
    static private function selMaterielPartStep2($paramsArr, $id, $goodsInfo, $data)
    {
        $sellOutStorageNewData = [];//首次出库信息
        $sellOutStorageAgainData = [];//再次出库信息

        foreach($goodsInfo as $key => $value) {
            $materielTypeInfo = MaterielsTypeModel::where('id', $value['materiel_type_id'])
                ->first();

            $storageManageInfo = StorageManageModel::select(
                'a.id',
                'type_id',
                'b.materiel_name',
                'b.materiel_no',
                'b.type_name',
                'storage_id',
                'c.storage_name',
                'a.in_storage_num'
            )
                ->from('storage_manage as a')
                ->leftJoin('materiel_type as b', 'b.id', '=', 'a.type_id')
                ->leftJoin('storage as c', 'c.id', '=', 'a.storage_id')
                ->where([
                    'a.delete_flag' => 0,
                    'storage_id' => $value['warehouse_id'],
                    'type_id' => $value['materiel_type_id'],
                ])
                ->first();

            $sellGoodsInfo = SellGoodsDetailModel::where([
                'sell_id' => $id,
                'materiel_type_id' => $value['materiel_type_id']
            ])
                ->first();

            $restNum = $sellGoodsInfo['num'] - $sellGoodsInfo['out_name'];

            if($restNum < $value['num']) {
                return [
                    'code' => 1,
                    'msg' => '销售单商品:'.$materielTypeInfo['materiel_name'].'-'.$materielTypeInfo['type_name'].
                        '可操作数量不足，当前可操作数量'.$restNum,
                    'data' => ''
                ];
            }

            if(empty($storageManageInfo)) {
                return [
                    'code' => 1,
                    'msg' => '商品:'.$materielTypeInfo['materiel_name'].'-'.$materielTypeInfo['type_name'].'库存信息不存在，无法出库',
                    'data' => ''
                ];
            }

            if(empty($value['batch_info'])) {
                return ['code' => 1, 'msg' => '请为商品:'.$materielTypeInfo['materiel_name'].'-'.$materielTypeInfo['type_name'].'选择批次号', 'data' => ''];
            }

            $paramsArr['content'][$key]['detail_id'] = $sellGoodsInfo['id'];
            $paramsArr['content'][$key]['storage_manage_id'] = $storageManageInfo['id'];
            $paramsArr['content'][$key]['price'] = $value['price'];
            $paramsArr['content'][$key]['num'] = $value['num'];
            $paramsArr['content'][$key]['remark'] = $value['remark'];
            $paramsArr['content'][$key]['in_storage_time'] = strtotime($data['in_storage_time']);
            $paramsArr['content'][$key]['warehouse_id'] = $storageManageInfo['storage_id'];

            //单个商品总批次数量
            $totalBatchNum = 0;
            foreach($value['batch_info'] as $k => $val) {
                $totalBatchNum += $val['num'];

                //批次号信息
                $BatchInfo = StorageBatchModel::where('id', $val['batch_id'])->first();
                //批次号对应的库存信息
                $storageBatchInfo = StorageManageModel::where('id', $val['storage_manage_id'])->first();

                if($storageBatchInfo['materiel_type_id'] != $value['materiel_type_id']) {
                    return [
                        'code' => 1,
                        'msg' => '批次号对应的商品和需出库商品信息不一致，无法完成操作',
                        'data' => ''
                    ];
                }

                //销售单商品批次数量
                $goodsDetailBatchInfo = SellGoodsDetailBatchModel::where([
                    'sell_id' => $id,
                    'storage_batch_id' => $val['batch_id']
                ])
                    ->first();

                if($val['num'] > $goodsDetailBatchInfo['rest_num']) {
                    return [
                        'code' => 1,
                        'msg' => '销售单内商品存在可出库的批次数量不足，无法完成出库操作',
                        'data' => ''
                    ];
                }

                if($val['num'] > $BatchInfo['batch_num']) {
                    return [
                        'code' => 1,
                        'msg' => '批次号:'.$BatchInfo['batch_no'].'库存数量不足，无法完成出库操作',
                        'data' => ''
                    ];
                }

                $paramsArr['content'][$key]['batch_info'][] =  [
                    'batch_id' => $BatchInfo['id'],
                    'num' => $val['num'],
                    'storage_manage_id' => $BatchInfo['storage_manage_id'],
                ];
            }

            //验证单个商品批次总数是否与该商品所需出库数量相符
            if($value['num'] < $totalBatchNum) {
                return [
                    'code' => 1,
                    'msg' => '商品:'.
                        $materielTypeInfo['materiel_name'].'-'.$materielTypeInfo['type_name'].
                        '批次出库数量超出该商品需出库数量,批次总数:'.$totalBatchNum.',超出数量:'.($totalBatchNum - $value['num']),
                    'data' => ''
                ];
            }

            if($value['num'] > $totalBatchNum) {
                return [
                    'code' => 1,
                    'msg' => '商品:'.
                        $materielTypeInfo['materiel_name'].'-'.$materielTypeInfo['type_name'].
                        '批次出库数量小于该商品需出库数量,批次总数:'.$totalBatchNum.',缺少数量:'.($value['num'] - $totalBatchNum),
                    'data' => ''
                ];
            }

            if($storageManageInfo['in_storage_num'] < $totalBatchNum) {
                return [
                    'code' => 1,
                    'msg' => '库存数量不足，无法出库',
                    'data' => ''
                ];
            }

            //销售单商品出库记录
            $sellOutStorageInfo = SellOutStorageModel::where([
                'materiel_type_id' => $value['materiel_type_id'],
                'sell_id' => $id
            ])->first();

            //验证是否已经出库
            if(empty($sellOutStorageInfo)) {
                $sellOutStorageNewData[$key]['sell_id'] = $id;
                $sellOutStorageNewData[$key]['name'] = $storageManageInfo['materiel_name'];
                $sellOutStorageNewData[$key]['type_name'] = $storageManageInfo['type_name'];
                $sellOutStorageNewData[$key]['num'] = $totalBatchNum;
                $sellOutStorageNewData[$key]['price'] = $value['price'];
                $sellOutStorageNewData[$key]['warehouse'] = $storageManageInfo['storage_name'];
                $sellOutStorageNewData[$key]['warehouse_id'] = $storageManageInfo['storage_id'];
                $sellOutStorageNewData[$key]['materiel_type_id'] = $storageManageInfo['type_id'];
                $sellOutStorageNewData[$key]['remark'] = empty($value['remark'])?'':$value['remark'];
            }
            else {
                $sellOutStorageAgainData[$key]['id'] = $sellOutStorageInfo['id'];
                $sellOutStorageAgainData[$key]['num'] = $totalBatchNum;
            }
        }

        return ['data' => $paramsArr, 'data1' => $sellOutStorageNewData, 'data2' => $sellOutStorageAgainData];
    }

    //撤销
    static public function repealWithBatch($id)
    {
        $sellInfo = SellModel::where('id', $id)->first();

        if($sellInfo['repeal_status']) {
            return ['code' => 1, 'msg' => '当前销售单已被撤销，请勿重复操作', 'data' => ''];
        }

        DB::beginTransaction();

        try {
            SellModel::where('id', $id)->update(['repeal_status' => 1]);
            CheckModel::where([
                'type' => 2,
                'all_id' => $id
            ])
                ->update([
                    'repeal_status' => 1
                ]);

            LogOutPackageModel::where([
                'all_id_type' => 2,
                'all_id' => $id
            ])
                ->update([
                    'is_cancel' => 1
                ]);

            $sellGoodsOutLogInfo = LogOutStorageModel::select(
                'curr_storage_manage_id as storage_manage_id',
                'operate_num',
                'storage_batch_id'
            )->where([
                'all_id_type' => 2,
                'all_id' => $id
            ])
                ->get()->toArray();

            $sellPackageContentLog = LogPackageContentModel::select(
                'out_storage_manage_id as storage_manage_id',
                'operate_num',
                'storage_batch_id'
            )
                ->where([
                    'all_id_type' => 4,
                    'all_id' => $id
                ])
                ->get()->toArray();

            if(!empty($sellGoodsOutLogInfo)) {
                foreach($sellGoodsOutLogInfo as $value) {
                    StorageManageModel::where('id', $value['storage_manage_id'])
                        ->update([
                            'in_storage_num' => DB::raw("in_storage_num + ".$value['operate_num']),
                            'virtual_storage_num' => DB::raw("virtual_storage_num + ".$value['operate_num'])
                        ]);

                    if($value['storage_batch_id'] != 0) {
                        StorageBatchModel::where('id', $value['storage_batch_id'])
                            ->increment('batch_left_num', $value['operate_num']);
                    }
                }
            }

            if(!empty($sellPackageContentLog)) {
                foreach($sellPackageContentLog as $values) {
                    StorageManageModel::where('id', $values['storage_manage_id'])
                        ->update([
                            'in_storage_num' => DB::raw("in_storage_num + ".$values['operate_num']),
                            'virtual_storage_num' => DB::raw("virtual_storage_num + ".$values['operate_num'])
                        ]);

                    if($values['storage_batch_id'] != 0) {
                        StorageBatchModel::where('id', $values['storage_batch_id'])
                            ->increment('batch_left_num', $values['operate_num']);
                    }
                }
            }

            DB::commit();
            return ['code' => 0, 'msg' => 'success', 'data' => ''];
        }
        catch(Exception $e) {
            DB::rollBack();
            Log::debug('销售单撤销'.var_export($e->getMessage(), true));
            return ['code' => 1, 'msg' => '销售单撤销异常', 'data' => ''];
        }
    }

    static public function sellAddBatch($data)
    {
        DB::beginTransaction();

        try {
            $info = json_decode($data['info'], true);
            if($data['type'] == 0) {
                $goodsDetialInfo = SellGoodsDetailModel::where([
                    'id' => $data['id'],
                    'sell_id' => $data['sell_id']
                ])
                    ->first();

                $totalNum = 0;

                $batchId = [];
                foreach($info as $value) {
                    $batchId[] = $value['batch_id'];
                    $totalNum += $value['num'];
                }

                $goodsDetailBatchInfo =  SellGoodsDetailBatchModel::select(
                    DB::raw('SUM(rest_num) as total_rest_num')
                )
                    ->where([
                        'sell_goods_detail_id' => $data['id'],
                        'sell_id' => $data['sell_id']
                    ])
                    ->whereIn('storage_batch_id', $batchId)
                    ->first();

                if(($goodsDetialInfo['num'] - $goodsDetialInfo['out_num']) < ($goodsDetailBatchInfo['total_rest_num'] + $totalNum)) {
                    return ['code' => 1, 'msg' => '当前商品批次总数超出商品所需数量，无法设置，请重试', 'data' => ''];
                }

                if(empty($goodsDetailBatchInfo['total_rest_num'])) {
                    foreach($info as $val) {
                        SellGoodsDetailBatchModel::insert([
                            'storage_batch_id' => $val['batch_id'],
                            'sell_goods_detail_id' => $data['id'],
                            'storage_manage_id' => $val['storage_manage_id'],
                            'sell_id' => $data['sell_id'],
                            'main_id' => $data['main_id'],
                            'num' => $val['num'],
                            'rest_num' => $val['num'],
                            'created_at' => time()
                        ]);
                    }
                }
                else {
                    foreach($info as $v) {
                        $goodsDetailBatchInfos = SellGoodsDetailBatchModel::where([
                            'sell_goods_detail_id' => $data['id'],
                            'storage_batch_id' => $v['batch_id'],
                            'sell_id' => $data['sell_id']
                        ])
                            ->first();

                        SellGoodsDetailBatchModel::where('id', $goodsDetailBatchInfos['id'])
                            ->update([
                                'num' => DB::raw("num + " . $v['num']),
                                'rest_num' => DB::raw("rest_num + " . $v['num'])
                            ]);
                    }
                }
            }
            else {
                $packageContentInfo = SellPackageContentModel::where([
                    'id' => $data['id'],
                    'sell_id' => $data['sell_id']
                ])->first();

                $totalNum = 0;
                $batchId = [];
                foreach($info as $value) {
                    $batchId[] = $value['batch_id'];
                    $totalNum += $value['num'];
                }

                $totalRestNum = SellPackageBatchModel::select(
                    DB::raw('SUM(rest_num) as total_rest_num')
                )
                    ->where([
                        'sell_package_content_id' => $data['id'],
                        'sell_id' => $data['sell_id']
                    ])
                    ->whereIn('storage_batch_id', $batchId)
                    ->first();

                if(($totalRestNum['total_rest_num'] + $totalNum) > $packageContentInfo['rest_num']) {
                    throw new Exception('单个商品批次数量超出套餐内商品所需数量');
                }

                if(empty($totalRestNum['total_rest_num'])) {
                    foreach($info as $val) {
                        SellPackageBatchModel::insert([
                            'sell_package_content_id' => $data['id'],
                            'storage_manage_id' => $val['storage_manage_id'],
                            'storage_batch_id' => $val['batch_id'],
                            'sell_id' => $data['sell_id'],
                            'main_id' => $data['main_id'],
                            'num' => $val['num'],
                            'rest_num' => $val['num'],
                            'created_at' => time()
                        ]);
                    }
                }
                else {
                    foreach($info as $v) {
                        $contentBatchInfo = SellPackageBatchModel::where([
                            'sell_package_content_id' => $data['id'],
                            'storage_batch_id' => $v['batch_id'],
                            'sell_id' => $data['sell_id']
                        ])
                            ->first();

                        SellPackageBatchModel::where('id', $contentBatchInfo['id'])
                            ->update([
                                'num' => DB::raw("num + ".$v['num']),
                                'rest_num' => DB::raw("rest_num + ".$v['num'])
                            ]);
                    }
                }
            }

            DB::commit();
            return ['code' => 0, 'msg' => 'success', 'data' => ''];
        }
        catch(Exception $e) {
            DB::rollBack();
            Log::debug('添加批次号异常'.var_export($e->getMessage(), true));
            return ['code' => 1, 'msg' => $e->getMessage(), 'data' => ''];
        }
    }

    static public function sellBatchList($data)
    {
        if($data['type'] == 0) {
            return SellGoodsDetailModel::select(
                'b.id',
                'c.batch_no',
                'in_storage_num',
                'b.rest_num',
                'c.batch_left_num',
                'e.materiel_name',
                'e.type_name',
                'materiel_type_id',
                'b.num',
            )
                ->from('sell_goods_detail as a')
                ->leftJoin('sell_goods_detail_batch as b', 'a.id', '=', 'b.sell_goods_detail_id')
                ->leftJoin('storage_batch as c', 'c.id', '=', 'b.storage_batch_id')
                ->leftJoin('storage_manage as d', 'd.id', '=', 'c.storage_manage_id')
                ->leftJoin('materiel_type as e', 'e.id', '=', 'd.type_id')
                ->where([
                    'a.materiel_type_id' => $data['materiel_type_id'],
                    'a.sell_id' => $data['id'],
                    'a.id' => $data['content_id']
                ])
                ->whereNotNull('c.batch_no')
                ->get()
                ->toArray();
        }
        else {
            return SellPackageContentModel::select(
                'b.id',
                'c.batch_no',
                'in_storage_num',
                'b.rest_num',
                'c.batch_left_num',
                'e.materiel_name',
                'e.type_name',
                'materiel_type_id',
                'b.num'
            )
                ->from('sell_package_content as a')
                ->leftJoin('sell_package_batch as b', 'b.sell_package_content_id', '=', 'a.id')
                ->leftJoin('storage_batch as c', 'c.id', '=', 'b.storage_batch_id')
                ->leftJoin('storage_manage as d', 'd.id', '=', 'c.storage_manage_id')
                ->leftJoin('materiel_type as e', 'e.id', '=', 'd.type_id')
                ->where([
                    'a.materiel_type_id' => $data['materiel_type_id'],
                    'a.sell_id' => $data['id'],
                    'a.id' => $data['content_id']
                ])
                ->whereNotNull('c.batch_no')
                ->get()
                ->toArray();
        }
    }

    //编辑套餐内商品批次信息
    static public function sellBatchEdit($data)
    {
        if($data['type'] == 0) {//销售单商品
            //目标批次信息
            $targetBatchInfo = SellGoodsDetailBatchModel::getTargetBatchInfo($data['goods_batch_id']);
            //所有商品批次信息
            $allGoodsBatchInfo = SellGoodsDetailBatchModel::getAllBatchNum($targetBatchInfo['sell_goods_detail_id']);
            //销售单内商品信息
            $sellGoodsDetailInfo = SellGoodsDetailModel::where('id', $targetBatchInfo['sell_goods_detail_id'])
                ->first();

            if($sellGoodsDetailInfo['num'] == $sellGoodsDetailInfo['out_num']) {
                return ['code' => 1, 'msg' => '商品已全部出库，无法修改', 'data' => ''];
            }

            //剔除已有库存剩余数量
            $beforeNum = $allGoodsBatchInfo['total_rest_num'] - $targetBatchInfo['rest_num'];
            //修改后的数量
            $afterNum = $beforeNum + $data['num'];

            if(($sellGoodsDetailInfo['num'] - $sellGoodsDetailInfo['out_num']) < $afterNum) {
                return ['code' => 1, 'msg' => '修改后的批次数量超出商品可出库数量,无法完成操作', 'data' => ''];
            }

            $targetBatchNewNum = ($targetBatchInfo['num'] - $targetBatchInfo['rest_num']) + $data['num'];

            SellGoodsDetailBatchModel::where('id', $data['goods_batch_id'])
                ->update([
                    'num' => $targetBatchNewNum,
                    'rest_num' => $data['num']
                ]);
        }
        else {//销售单内套餐商品
            $targetBatchInfo = SellPackageBatchModel::getTargetBatchInfo($data['goods_batch_id']);
            $allBatchInfo = SellPackageBatchModel::getAllBatchNum($targetBatchInfo['sell_package_content_id']);
            $sellPackageContentInfo = SellPackageContentModel::where('id', $targetBatchInfo['sell_package_content_id'])->first();

            if($sellPackageContentInfo['rest_num'] == 0) {
                return ['code' => 1, 'msg' => '商品已全部出库，无法修改', 'data' => ''];
            }

            //剔除已有库存剩余数量
            $beforeNum = $allBatchInfo['total_rest_num'] - $targetBatchInfo['rest_num'];
            //修改后的数量
            $afterNum = $beforeNum + $data['num'];

            if(($sellPackageContentInfo['total_num'] - $sellPackageContentInfo['rest_num']) < $afterNum) {
                return ['code' => 1, 'msg' => '修改后的批次数量超出商品可出库数量,无法完成操作', 'data' => ''];
            }

            $targetBatchNewNum = ($targetBatchInfo['num'] - $targetBatchInfo['rest_num']) + $data['num'];

            SellPackageBatchModel::where('id', $data['goods_batch_id'])
                ->update([
                    'num' => $targetBatchNewNum,
                    'rest_num' => $data['num']
                ]);
        }

        return ['code' => 0, 'msg' => 'success', 'data' => ''];
    }
}
